diff --git a/artTools/normalize_svg.py b/artTools/normalize_svg.py old mode 100644 new mode 100755 index e189f619d402c749d120e022f1867a3e61ab9db9..2ee6e332a84780197d9aca379a0dd5d558598930 --- a/artTools/normalize_svg.py +++ b/artTools/normalize_svg.py @@ -17,71 +17,95 @@ python3 inkscape_svg_fixup.py vector_source.svg import lxml.etree as etree import sys +import re + +color_classes = { + 'skin', 'head', 'torso', 'boob', 'penis', 'scrotum', 'belly', + 'areola', 'bellybutton', 'labia', 'hair', 'pubic_hair', 'underarm_hair', + 'eyebrow_hair', 'shoe', 'shoe_shadow', 'smart_piercing', 'steel_piercing', + 'steel_chastity', 'outfit_base', 'gag', 'shadow', 'glasses', 'eye', 'sclera' +} + def fix(tree): - # know namespaces - ns = { - 'svg' : 'http://www.w3.org/2000/svg', - 'inkscape' : 'http://www.inkscape.org/namespaces/inkscape' - } - - # find document global style definition - # mangle it and interpret as python dictionary - style_element = tree.find('./svg:style',namespaces=ns) - style_definitions = style_element.text - pythonic_style_definitions = '{'+style_definitions.\ - replace('\t.','"').replace('{','":"').replace('}','",').\ - replace('/*','#')+'}' - styles = eval(pythonic_style_definitions) - - # go through all SVG elements - for elem in tree.iter(): - if (elem.tag == etree.QName(ns['svg'], 'g')): - # compare inkscape label with group element ID - l = elem.get(etree.QName(ns['inkscape'], 'label')) - if l: - i = elem.get('id') - if (i != l): - print("Overwriting ID %s with Label %s..."%(i, l)) - elem.set('id', l) - - # clean styles (for easier manual merging) - style_string = elem.get('style') - if style_string: - split_styles = style_string.strip('; ').split(';') - styles_pairs = [s.strip('; ').split(':') for s in split_styles] - filtered_pairs = [ (k,v) for k,v in styles_pairs if not ( - k.startswith('font-') or - k.startswith('text-') or - k.endswith('-spacing') or - k in ["line-height", " direction", " writing", " baseline-shift", " white-space", " writing-mode"] - )] - split_styles = [':'.join(p) for p in filtered_pairs] - style_string = ';'.join(sorted(split_styles)) - elem.attrib["style"] = style_string - - # remove all style attributes offending class styles - s = elem.get('style') - c = elem.get('class') - if (c and s): - s = s.lower() - c = c.split(' ')[0] # regard main style only - cs = '' - if c in styles: - cs = styles[c].strip('; ').lower() - if (c not in styles): - print("Object id %s references unknown style class %s."%(i,c)) - else: - if (cs != s.strip('; ')): - print("Style %s removed from object id %s differed from class %s style %s."%(s,i,c,cs)) - del elem.attrib["style"] + # know namespaces + ns = { + 'svg': 'http://www.w3.org/2000/svg', + 'inkscape': 'http://www.inkscape.org/namespaces/inkscape' + } + + # find document global style definition + # mangle it and interpret as python dictionary + style_element = tree.find('./svg:style', namespaces=ns) + style_definitions = style_element.text + pythonic_style_definitions = '{'+style_definitions.\ + replace('\t.', '"').replace('{', '":"').replace('}', '",').\ + replace('/*', '#')+'}' + styles = eval(pythonic_style_definitions) + + # go through all SVG elements + for elem in tree.iter(): + if (elem.tag == etree.QName(ns['svg'], 'g')): + # compare inkscape label with group element ID + lbl = elem.get(etree.QName(ns['inkscape'], 'label')) + if lbl: + i = elem.get('id') + if (i != lbl): + print("Overwriting ID %s with Label %s..." % (i, lbl)) + elem.set('id', lbl) + + # clean styles (for easier manual merging) + style_string = elem.get('style') + if style_string: + split_styles = style_string.strip('; ').split(';') + styles_pairs = [s.strip('; ').split(':') for s in split_styles] + filtered_pairs = [(k, v) for k, v in styles_pairs if not ( + k.startswith('font-') or + k.startswith('text-') or + k.endswith('-spacing') or + k in ["line-height", " direction", " writing", " baseline-shift", " white-space", " writing-mode"] + )] + split_styles = [':'.join(p) for p in filtered_pairs] + style_string = ';'.join(sorted(split_styles)) + elem.attrib["style"] = style_string + + # remove all style attributes offending class styles + s = elem.get('style') + c = elem.get('class') + if (c and s): + s = s.lower() + c = c.split(' ')[0] # regard main style only + classes = c.split(' ') + hasColorClass = any(x in color_classes for x in classes) + if hasColorClass: + s_new = re.sub('fill:#[0-9a-f]+;?', '', s) + if s != s_new: + print("Explicit fill was removed from style string ({0}) for element with ID {1} " + "because its class ({2}) controls the fill color".format(s, i, c)) + s = s_new + if s == 'style=""': # the style is empty now + del elem.attrib["style"] + continue + cs = '' + if c in styles: + cs = styles[c].strip('; ').lower() + if (c not in styles): + print("Object id %s references unknown style class %s." % (i, c)) + else: + if (cs != s.strip('; ')): + print("Style %s removed from object id %s differed from class %s style %s." % (s, i, c, cs)) + del elem.attrib["style"] + + # remove explicit fill color if element class is one of the color_classes + + if __name__ == "__main__": - input_file = sys.argv[1] - tree = etree.parse(input_file) - fix(tree) - # store SVG into file (input file is overwritten) - svg = etree.tostring(tree, pretty_print=True) - with open(input_file, 'wb') as f: - f.write('<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n'.encode("utf-8")) - f.write(svg) + input_file = sys.argv[1] + tree = etree.parse(input_file) + fix(tree) + # store SVG into file (input file is overwritten) + svg = etree.tostring(tree, pretty_print=True) + with open(input_file, 'wb') as f: + f.write('<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n'.encode("utf-8")) + f.write(svg) diff --git a/artTools/vector_layer_split.py b/artTools/vector_layer_split.py old mode 100644 new mode 100755 index abff29fc4a76be031dd870bdb69917b4ff70f629..4c231df6a40000cb6e2ef0b92754dd4d2e1c5a5b --- a/artTools/vector_layer_split.py +++ b/artTools/vector_layer_split.py @@ -16,109 +16,126 @@ import os import copy import re import normalize_svg +import argparse + +parser = argparse.ArgumentParser( + description='Application for splitting groups from one SVG file into separate files.') +parser.add_argument('-o', '--output', dest='output_dir', required=True, + help='output directory') +parser.add_argument('-f', '--format', dest='output_format', + choices=['svg', 'tw'], default='svg', help='output format.') +parser.add_argument('-p', '--prefix', dest='prefix', default='', + help='Prepend this string to result file names') +parser.add_argument('input_file', metavar='FILENAME', nargs='+', + help='Input SVG file with layers') + +args = parser.parse_args() +output_format = args.output_format +output_directory = args.output_dir + + +def splitFile(inputFile): + tree = etree.parse(inputFile) + normalize_svg.fix(tree) + + # prepare output template + template = copy.deepcopy(tree) + root = template.getroot() + + # remove all svg root attributes except document size + for a in root.attrib: + if (a != "viewBox"): + del root.attrib[a] + + # add placeholder for CSS class (needed for workaround for non HTML 5.1 compliant browser) + # if output_format == 'tw': + # root.attrib["class"] = "'+_art_display_class+'" + ns = { + 'svg': 'http://www.w3.org/2000/svg', + 'inkscape': 'http://www.inkscape.org/namespaces/inkscape', + 'sodipodi': "http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd", + } + + # remove all content, including metadata + # for twine output, style definitions are removed, too + defs = None + for e in root: + if (e.tag == etree.QName(ns['svg'], 'defs')): + defs = e + if (e.tag == etree.QName(ns['svg'], 'g') or + e.tag == etree.QName(ns['svg'], 'metadata') or + e.tag == etree.QName(ns['svg'], 'defs') or + e.tag == etree.QName(ns['sodipodi'], 'namedview') or + (output_format == 'tw' and e.tag == etree.QName(ns['svg'], 'style')) + ): + root.remove(e) + # template preparation finished + + # prepare regex for later use + regex_xmlns = re.compile(' xmlns[^ ]+') + regex_space = re.compile(r'[>]\s+[<]') + + # find all groups + layers = tree.xpath('//svg:g', namespaces=ns) + for layer in layers: + i = layer.get('id') + if ( # disregard non-content groups + i.endswith("_") or # manually suppressed with underscore + i.startswith("XMLID") or # Illustrator generated group + i.startswith("g") # Inkscape generated group + ): + continue + # create new canvas + output = copy.deepcopy(template) + # copy all shapes into template + canvas = output.getroot() + for e in layer: + canvas.append(e) + # represent template as SVG (binary string) + svg = etree.tostring(output, pretty_print=False) + # poor man's conditional defs insertion + # TODO: extract only referenced defs (filters, gradients, ...) + # TODO: detect necessity by traversing the elements. do not stupidly search in the string representation + if ("filter:" in svg.decode('utf-8')): + # it seems there is a filter referenced in the generated SVG, re-insert defs from main document + canvas.insert(0, defs) + # re-generate output + svg = etree.tostring(output, pretty_print=False) + + if (output_format == 'tw'): + # remove unnecessary attributes + # TODO: never generate unnecessary attributes in the first place + svg = svg.decode('utf-8') + svg = regex_xmlns.sub('', svg) + svg = svg.replace(' inkscape:connector-curvature="0"', '') # this just saves space + svg = svg.replace('\n', '').replace('\r', '') # print cannot be multi-line + svg = regex_space.sub('><', svg) # remove indentation + svg = svg.replace('svg:', '') # svg namespace was removed + if ("Boob" in i): # internal groups are used for scaling + svg = svg.replace('<g ', '<g data-transform="boob" ') # boob art uses the boob scaling + elif ("Belly" in i): + svg = svg.replace('<g ', '<g data-transform="belly" ') # belly art uses the belly scaling + else: + svg = svg.replace('<g ', '<g data-transform="art" ') # otherwise use default scaling + if (not svg.endswith('\n')): + svg += '\n' + svg = svg.encode('utf-8') + + # save SVG string to file + i = layer.get('id') + output_path = os.path.join(output_directory, "{0}{1}.svg".format(args.prefix, i)) + with open(output_path, 'wb') as f: + if (output_format == 'svg'): + # Header for normal SVG (XML) + f.write('<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n'.encode("utf-8")) + f.write(svg) + elif (output_format == 'tw'): + f.write(svg) + -input_file = sys.argv[1] -output_format = sys.argv[2] -output_directory = sys.argv[3] if not os.path.exists(output_directory): os.makedirs(output_directory) -ns = { - 'svg' : 'http://www.w3.org/2000/svg', - 'inkscape' : 'http://www.inkscape.org/namespaces/inkscape', - 'sodipodi':"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd", -} - -tree = etree.parse(input_file) -normalize_svg.fix(tree) - -# prepare output template -template = copy.deepcopy(tree) -root = template.getroot() - -# remove all svg root attributes except document size -for a in root.attrib: - if (a != "viewBox"): - del root.attrib[a] - -# add placeholder for CSS class (needed for workaround for non HTML 5.1 compliant browser) -if output_format == 'tw': - root.attrib["class"] = "'+_art_display_class+'" - -# remove all content, including metadata -# for twine output, style definitions are removed, too -defs = None -for e in root: - if (e.tag == etree.QName(ns['svg'], 'defs')): - defs = e - if (e.tag == etree.QName(ns['svg'], 'g') or - e.tag == etree.QName(ns['svg'], 'metadata') or - e.tag == etree.QName(ns['svg'], 'defs') or - e.tag == etree.QName(ns['sodipodi'], 'namedview') or - (output_format == 'tw' and e.tag == etree.QName(ns['svg'], 'style')) - ): - root.remove(e) -# template preparation finished - -# prepare regex for later use -regex_xmlns = re.compile(' xmlns[^ ]+',) -regex_space = re.compile('[>][ ]+[<]',) - -# find all groups -layers = tree.xpath('//svg:g',namespaces=ns) -for layer in layers: - i = layer.get('id') - if ( # disregard non-content groups - i.endswith("_") or # manually suppressed with underscore - i.startswith("XMLID") or # Illustrator generated group - i.startswith("g") # Inkscape generated group - ): - continue - # create new canvas - output = copy.deepcopy(template) - # copy all shapes into template - canvas = output.getroot() - for e in layer: - canvas.append(e) - # represent template as SVG (binary string) - svg = etree.tostring(output, pretty_print=False) - # poor man's conditional defs insertion - # TODO: extract only referenced defs (filters, gradients, ...) - # TODO: detect necessity by traversing the elements. do not stupidly search in the string representation - if ("filter:" in svg.decode('utf-8')): - # it seems there is a filter referenced in the generated SVG, re-insert defs from main document - canvas.insert(0,defs) - # re-generate output - svg = etree.tostring(output, pretty_print=False) - - if (output_format == 'tw'): - # remove unnecessary attributes - # TODO: never generate unnecessary attributes in the first place - svg = svg.decode('utf-8') - svg = regex_xmlns.sub('',svg) - svg = svg.replace(' inkscape:connector-curvature="0"','') # this just saves space - svg = svg.replace('\n','').replace('\r','') # print cannot be multi-line - svg = regex_space.sub('><',svg) # remove indentation - svg = svg.replace('svg:','') # svg namespace was removed - if ("Boob" in i): # internal groups are used for scaling - svg = svg.replace('<g ','<g transform="\'+_artTransformBoob+\'"') # boob art uses the boob scaling - elif ("Belly" in i): - svg = svg.replace('<g ','<g transform="\'+_artTransformBelly+\'"') # belly art uses the belly scaling - else: - svg = svg.replace('<g ','<g transform="\'+_art_transform+\'"') # otherwise use default scaling - svg = svg.encode('utf-8') - - # save SVG string to file - i = layer.get('id') - output_path = os.path.join(output_directory,i+'.'+output_format) - with open(output_path, 'wb') as f: - if (output_format == 'svg'): - # Header for normal SVG (XML) - f.write('<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n'.encode("utf-8")) - f.write(svg) - elif (output_format == 'tw'): - # Header for SVG in Twine file (SugarCube print statement) - f.write((':: Art_Vector_%s [nobr]\n\n'%(i)).encode("utf-8")) - f.write("<<print '<html>".encode("utf-8")) - f.write(svg) - f.write("</html>' >>".encode("utf-8")) +for f in args.input_file: + splitFile(f) + diff --git a/artTools/vector_revamp_layer_split.py b/artTools/vector_revamp_layer_split.py old mode 100644 new mode 100755 index eee6817c4f896abfe876c250a992e3ea06d7cd31..13c19faddd55a119ff9475af0a3ce3d353a2cb0e --- a/artTools/vector_revamp_layer_split.py +++ b/artTools/vector_revamp_layer_split.py @@ -17,11 +17,26 @@ import sys import os import copy import re +import argparse import normalize_svg -input_file = sys.argv[1] -output_format = sys.argv[2] -output_directory = sys.argv[3] +parser = argparse.ArgumentParser( + description='Application for splitting groups from one SVG file into separate files.') +parser.add_argument('-o', '--output', dest='output_dir', required=True, + help='output directory') +parser.add_argument('-f', '--format', dest='output_format', + choices=['svg', 'tw'], default='svg', help='output format.') +parser.add_argument('-p', '--prefix', dest='prefix', default='', + help='Prepend this string to result file names') +parser.add_argument('input_file', metavar='FILENAME', nargs=1, + help='Input SVG file with layers') + +args = parser.parse_args() + +output_format = args.output_format +output_directory = args.output_dir +input_file = args.input_file[0] + if not os.path.exists(output_directory): os.makedirs(output_directory) @@ -46,10 +61,6 @@ for a in root.attrib: if (a != "viewBox"): del root.attrib[a] -# add placeholder for CSS class (needed for workaround for non HTML 5.1 compliant browser) -if output_format == 'tw': - root.attrib["class"] = "'+_art_display_class+'" - # remove all content, including metadata # for twine output, style definitions are removed, too defs = None @@ -66,11 +77,9 @@ for e in root: # template preparation finished # prepare regex for later use -regex_xmlns = re.compile(' xmlns[^ ]+', ) -regex_space = re.compile('[>][ ]+[<]', ) -regex_transformValue = re.compile('(?<=transformVariableName=")[^"]*', ) -regex_transformVar = re.compile('transformVariableName="[^"]*"', ) -regex_transformAttr = re.compile('transform="[^"]*"', ) +regex_xmlns = re.compile(' xmlns[^ ]+') +regex_space = re.compile(r'[>]\s+[<]') + # find all groups layers = tree.xpath('//svg:g', namespaces=ns) for layer in layers: @@ -113,28 +122,17 @@ for layer in layers: svg = regex_space.sub('><', svg) # remove indentation svg = svg.replace('svg:', '') # svg namespace was removed - transformGroups = regex_transformVar.findall(svg) - - if (len(transformGroups) > 0): - svg = regex_transformAttr.sub('', svg) - for transformGroup in transformGroups: - transformValue = regex_transformValue.search(transformGroup) - if (transformValue is not None): - svg = svg.replace(transformGroup, ' transform="\'+' + transformValue.group() + '+\'" ') # internal groups are used for scaling - + if (not svg.endswith('\n')): + svg += '\n' svg = svg.encode('utf-8') # save SVG string to file i = layer.get('id') - output_path = os.path.join(output_directory, i + '.' + output_format) + output_path = os.path.join(output_directory, "{0}{1}.svg".format(args.prefix, i)) with open(output_path, 'wb') as f: if (output_format == 'svg'): # Header for normal SVG (XML) f.write('<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n'.encode("utf-8")) f.write(svg) elif (output_format == 'tw'): - # Header for SVG in Twine file (SugarCube print statement) - f.write((':: Art_Vector_Revamp_%s [nobr]\n\n' % (i)).encode("utf-8")) - f.write("<<print '<html>".encode("utf-8")) f.write(svg) - f.write("</html>' >>".encode("utf-8")) diff --git a/artTools/vector_revamp_source.svg b/artTools/vector_revamp_source.svg index 19b638e460cf4aec79f3951579f4dc551f3aee48..be0a37e3d9966552183446594d5f6b9d8ac94a9f 100644 --- a/artTools/vector_revamp_source.svg +++ b/artTools/vector_revamp_source.svg @@ -792,7 +792,7 @@ </g> </g> <g inkscape:groupmode="layer" id="Pubic_Hair_" inkscape:label="Pubic_Hair_" style="display:inline;opacity:1"> - <g inkscape:groupmode="layer" id="Pussy_Tattoo" inkscape:label="Pussy_Tattoo" style="display:inline"><path style="fill:none;stroke:none" d="m 253.62239,430.50769 c 14.1376,12.59209 60.92413,9.84192 72.85898,-5.2246" id="path4363" inkscape:connector-curvature="0" sodipodi:nodetypes="cc"/><text xml:space="preserve" id="text4365" style="font-size:12px;line-height:0%;text-align:center;text-anchor:middle" x="40.117271" y="19.936554" transform="translate(-3.125,0.875)"><textPath xlink:href="#path4363" id="textPath4369" style="font-size:12px;text-align:center;text-anchor:middle">'+_art_pussy_tattoo_text+'</textPath></text> + <g inkscape:groupmode="layer" id="Pussy_Tattoo" inkscape:label="Pussy_Tattoo" style="display:inline"><path style="fill:none;stroke:none" d="m 253.62239,430.50769 c 14.1376,12.59209 60.92413,9.84192 72.85898,-5.2246" id="path4363" inkscape:connector-curvature="0" sodipodi:nodetypes="cc"/><text xml:space="preserve" id="text4365" style="font-size:12px;line-height:0%;text-align:center;text-anchor:middle" x="40.117271" y="19.936554" transform="translate(-3.125,0.875)"><textPath xlink:href="#path4363" id="textPath4369" style="font-size:12px;text-align:center;text-anchor:middle" data-transform="pussy_tattoo_text">placeholder</textPath></text> </g> <g inkscape:groupmode="layer" id="Pubic_Hair_Bush" inkscape:label="Pubic_Hair_Bush" style="display:inline"> <path d="m 308.13404,461.37031 c -0.42215,-1.28729 0.0816,-2.88322 0.21937,-4.35713 0.83735,-0.9231 3.39354,-0.46675 4.27169,-0.32918 -1.30887,-1.90043 -2.57358,-4.54221 -2.26693,-6.80614 1.738,0.72332 5.26268,-0.10717 6.41461,-0.67323 -0.0359,-0.042 -3.73233,-5.5593 -3.73233,-5.5593 l 9.37697,-2.92546 c -2.29483,-1.16082 -2.9398,-3.27348 -0.88244,-5.06275 2.05735,-1.78926 4.65981,-3.19815 6.96574,-5.50002 2.30592,-2.30188 5.70181,-7.11497 7.1718,-9.21523 -3.30249,2.57531 -8.11937,4.56169 -12.38086,6.76405 3.87939,-4.08083 5.14191,-8.70938 6.56483,-13.30436 -2.75485,4.55035 -5.96287,8.80998 -11.80357,11.38073 0.0795,-2.69081 -1.1771,-5.33024 -2.60799,-7.96296 -0.22411,2.1009 0.65963,4.43504 -1.59857,6.10771 -1.87893,0.66093 -0.47641,0.32561 -1.63156,-0.61901 -1.15515,-0.94462 -1.07324,-2.86249 -0.92674,-4.77175 0.20638,0.15948 -5.2425,3.40307 -10.88069,2.89338 0.39636,-1.77718 -0.0929,-3.59654 -0.547,-5.41423 -1.43947,1.75633 -2.54315,3.7645 -5.73335,4.20778 -2.4605,-0.40363 -2.23191,-1.95973 -2.31051,-3.38418 -1.13808,1.43053 -1.96377,3.07348 -4.50289,3.5513 -1.9104,-1.28206 -0.74793,-2.77125 -0.61109,-4.22119 -1.53049,0.96737 -3.1427,1.90033 -3.58898,3.32421 -0.54093,-1.76679 -2.17255,-2.5156 -3.54365,-3.50756 -0.0389,1.41793 0.87573,3.17815 -1.27914,3.8365 -1.65822,-2.01275 -2.66902,-3.03894 -4.81025,-3.3656 0.25465,1.17773 3.29056,2.50997 -1.24916,3.42134 -2.99547,0.66615 -4.88472,-1.06452 -6.85325,-2.62341 1.01031,2.71963 1.71296,5.80844 3.5463,7.54043 -2.27359,-0.46197 -8.62398,-1.3164 -12.1147,-8.21411 -1.18774,2.82298 -3.39707,5.36503 -1.4599,9.04737 -4.08,-0.2462 -6.1875,-2.55065 -8.40846,-4.73671 0.87978,2.88663 0.68095,5.90808 3.36457,8.56923 -3.64826,0.33795 -6.3127,-1.29171 -9.26707,-2.34153 3.9514,4.60614 8.75627,7.56631 13.86823,9.93423 1.34859,1.27311 6.10477,6.04621 5.62068,7.31932 2.82401,-2.71219 1.92529,-1.87573 4.91302,-0.16768 2.79974,2.66519 2.83014,1.95151 3.16745,4.12421 1.92433,1.50259 3.84866,1.63676 5.77299,0.97623 0,0 -2.01653,2.6409 -4.35182,2.38868 1.74775,0.61934 4.06788,-0.37099 5.9306,-0.0583 1.77365,1.74778 0.43253,3.2124 -1.41503,4.63097 2.73367,-0.28074 5.4652,-0.70503 8.23933,1.72431 1.73622,1.49945 2.78135,3.0373 3.78142,4.57765 1.20741,0.19088 2.97961,-0.0117 1.69438,1.91564 0.94867,-0.32712 2.37843,-0.52377 1.68983,-1.29489 1.14987,0.78895 2.29975,0.66306 3.44962,0.4995 -0.7627,-0.5118 -1.8836,-1.08502 -0.37378,-1.68488 l -1.10478,-0.10762 -0.6613,-0.63638 c -0.0538,-0.38752 0.0965,-0.69562 0.57239,-0.87715 -0.55161,-0.19514 -0.82876,-0.0489 -0.99909,0.22508 0.0467,-0.74904 -0.0233,-1.52988 -0.30014,-2.36715 -0.37451,0.28516 -0.76038,0.25212 -1.16432,-0.28668 0.002,-0.91711 -0.0725,-1.84829 0.23704,-2.70958 -0.16694,0.37927 -0.59322,0.44156 -1.01892,0.50457 0.38567,-0.60697 0.46502,-1.15824 0.53332,-1.7075 -0.4944,0.29755 -1.11943,0.0252 -1.05496,-0.82437 0.33836,-0.10834 0.62446,-0.4585 0.67693,-0.79556 -0.43615,-0.85876 -0.10806,-1.64444 -0.0504,-2.55807 0.27076,0.89645 0.49642,1.81024 1.13611,2.5648 0.13715,-0.65786 0.62993,-1.03497 1.15644,-1.38545 0.48685,0.95084 0.54472,1.96297 0.4514,2.9967 0.23312,-0.65185 0.73464,-0.76691 1.27616,-0.80195 0.12849,0.90282 0.30765,1.81288 -0.27027,2.61479 0.54567,-0.30808 1.13159,-0.3075 1.62165,-1.04187 -0.0858,1.11195 -0.27643,2.20992 -0.67396,3.28031 0.25461,-0.26873 0.6401,-0.4284 0.66867,-0.8855 0.23427,0.66706 0.0246,1.11215 -0.0483,1.62563 0.11494,-0.22262 0.30901,-0.3028 0.63201,-0.15092 -0.23603,0.51298 -0.21479,0.99569 0.25629,1.42548 -0.0542,-0.28824 -0.10088,-0.57291 0.23199,-0.67779 0.40976,0.32368 0.52422,0.69166 0.51908,1.07758 -0.002,0.53232 -0.031,0.73901 0.15212,1.14793 -0.0165,-0.005 1.73831,1.6893 1.73831,1.6893 0.38852,-0.50132 0.92958,-0.77384 1.56782,-0.90059 1.1846,0.75012 2.56975,0.89857 3.88755,1.24905 -0.4332,-1.00083 0.027,-1.15529 0.77386,-1.03816 1.46038,-0.0697 1.24438,0.67559 1.26775,1.30448 1.46259,-1.00786 1.07324,-1.76849 1.50981,-2.14482 0.64839,0.13025 1.1895,0.0102 1.588,-0.44262 z" id="path4354-2" inkscape:connector-curvature="0" class="pubic_hair" sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"/> @@ -1613,72 +1613,72 @@ <g inkscape:groupmode="layer" id="Boob_" style="display:inline" inkscape:label="Boob_"> <g style="display:inline" inkscape:label="Boob_Huge_" id="Boob_Huge_" inkscape:groupmode="layer"> <g inkscape:groupmode="layer" id="Boob_Huge" style="display:inline;opacity:1" inkscape:label="Boob_Huge"> - <g id="g2276" transformVariableName="_boob_right_art_transform" transform="matrix(4,0,0,4,-750.12304,-598.08667)"> + <g id="g2276" data-transform="boob_right" transform="matrix(4,0,0,4,-750.12304,-598.08667)"> <path sodipodi:nodetypes="cccccccc" id="path2272" class="shadow" d="m 251.94799,202.06126 c -5.48922,8.60644 -14.21655,16.55553 -29.5132,24.802 -2.66627,10.79115 -4.57141,18.93814 5.09449,27.8494 6.92439,7.7255 14.82723,9.34865 24.00444,4.54068 9.9758,-4.87332 -2.88363,-0.91055 5.62068,-13.48656 0.51484,-8.64963 4.02743,-15.80582 5.08765,-21.2787 1.24098,-5.57972 1.78028,-10.00392 -5.51886,-16.34477 -5.28827,-4.59399 1.66486,-7.34429 -4.7752,-6.08205 z" inkscape:connector-curvature="0"/> <path inkscape:connector-curvature="0" d="m 251.94799,202.06126 c -4.58269,8.82904 -14.93008,17.30782 -29.5132,24.802 -2.39837,10.79115 -3.45193,18.69011 5.09449,27.8494 7.45154,6.95799 15.65465,8.14394 24.00444,4.54068 9.42591,-5.13062 -3.89307,-1.68704 5.62068,-13.48656 3.23278,-7.85413 5.17648,-15.27549 6.2367,-20.74837 1.24098,-5.57972 -0.87916,-14.57204 -5.2095,-19.8803 -1.46475,-1.79553 -0.006,-6.28363 -6.23361,-3.07685 z" class="skin boob" id="path2274" sodipodi:nodetypes="ccccccac"/> </g> - <g id="g2282" transformVariableName="_boob_left_art_transform" transform="matrix(4,0,0,4,-941.71671,-583.58668)"> + <g id="g2282" data-transform="boob_left" transform="matrix(4,0,0,4,-941.71671,-583.58668)"> <path inkscape:connector-curvature="0" d="m 322.52175,198.05651 c -4.11529,-0.17415 -4.6911,0.99135 -11.14734,1.40095 -6.05493,6.21998 -12.33211,13.08022 -17.97286,20.11452 -8.89026,9.35249 -11.15253,21.87785 -4.29471,30.50069 8.26604,12.77039 34.79999,12.67441 44.46576,0.60856 6.73235,-7.12225 6.42177,-20.48446 -1.27924,-30.36173 -5.66858,-9.77024 -9.11055,-18.938 -9.77161,-22.26299 z" class="shadow" id="path2307" sodipodi:nodetypes="ccccccc"/> <path sodipodi:nodetypes="ccssssc" id="path2280" class="skin boob" d="m 322.52175,198.05651 c -4.11529,-1.2502 -4.6911,-1.40468 -11.14734,1.40095 -5.76044,6.21998 -11.66471,13.08022 -17.97286,20.11452 -8.22932,9.17663 -10.424,21.68399 -4.29471,30.50069 8.32079,11.96907 34.87117,11.63286 44.46576,0.60856 6.19858,-7.12225 5.94519,-20.48446 -1.27924,-30.36173 -6.92244,-9.4644 -9.19482,-18.91693 -9.77161,-22.26299 z" inkscape:connector-curvature="0"/> </g> </g> <g inkscape:label="Boob_Huge_Areolae_Normal" style="display:inline;opacity:1" id="Boob_Huge_Areolae_Normal" inkscape:groupmode="layer"> - <g transformVariableName="_boob_right_art_transform" id="g2568" transform="matrix(4,0,0,4,-750.12304,-598.08667)"> + <g data-transform="boob_right" id="g2568" transform="matrix(4,0,0,4,-750.12304,-598.08667)"> <path sodipodi:nodetypes="czczsc" inkscape:connector-curvature="0" d="m 227.14891,224.34464 c 0,0 0.24231,2.57487 -0.69623,5.44459 -0.93851,2.86971 -5.64569,7.20295 -5.64569,7.20295 0,0 -1.26707,-4.99893 -0.96376,-6.1901 0.30329,-1.19118 0.50662,-1.84681 1.74593,-3.20091 1.5586,-1.70299 5.55975,-3.25653 5.55975,-3.25653 z" class="areola" id="path2566"/> </g> - <g transformVariableName="_boob_left_art_transform" id="g2572" transform="matrix(4,0,0,4,-941.71671,-583.58668)"> + <g data-transform="boob_left" id="g2572" transform="matrix(4,0,0,4,-941.71671,-583.58668)"> <path sodipodi:nodetypes="sssss" class="areola" d="m 309.93277,231.30328 c -3.40637,-0.37574 -6.84874,-2.88621 -6.8649,-5.13633 -0.0207,-2.87162 4.32444,-5.86871 8.14144,-5.70169 3.58937,0.15706 7.3351,2.49811 6.5993,5.97861 -0.7358,3.4805 -3.80292,5.30866 -7.87584,4.85941 z" id="path2570" inkscape:connector-curvature="0"/> </g> </g> <g inkscape:groupmode="layer" id="Boob_Huge_Areolae_Large" style="display:inline;opacity:1" inkscape:label="Boob_Huge_Areolae_Large"> - <g id="g2578" transformVariableName="_boob_right_art_transform" transform="matrix(4,0,0,4,-750.12304,-598.08667)"> + <g id="g2578" data-transform="boob_right" transform="matrix(4,0,0,4,-750.12304,-598.08667)"> <path id="path2576" class="areola" d="m 228.60733,223.47737 c 0,0 0.30094,3.19792 -0.8647,6.76203 -1.16561,3.5641 -7.01179,8.94586 -7.01179,8.94586 0,0 -1.57367,-6.20853 -1.19696,-7.68793 0.37668,-1.47941 0.62921,-2.29369 2.16839,-3.97544 1.93574,-2.11507 6.90506,-4.04452 6.90506,-4.04452 z" inkscape:connector-curvature="0" sodipodi:nodetypes="czczsc"/> </g> - <g id="g2582" transformVariableName="_boob_left_art_transform" transform="matrix(4,0,0,4,-941.71671,-583.58668)"> + <g id="g2582" data-transform="boob_left" transform="matrix(4,0,0,4,-941.71671,-583.58668)"> <path inkscape:connector-curvature="0" id="path2580" d="m 310.0179,234.96812 c -4.61957,-0.50956 -9.28796,-3.91415 -9.30987,-6.96566 -0.028,-3.89437 5.86461,-7.95889 11.04106,-7.73238 4.86774,0.213 9.94754,3.38782 8.94968,8.10792 -0.99786,4.72011 -5.15735,7.19938 -10.68087,6.59012 z" class="areola" sodipodi:nodetypes="sssss"/> </g> </g> <g inkscape:label="Boob_Huge_Areolae_Wide" style="display:inline;opacity:1" id="Boob_Huge_Areolae_Wide" inkscape:groupmode="layer"> - <g transformVariableName="_boob_right_art_transform" id="g2588" transform="matrix(4,0,0,4,-750.12304,-598.08667)"> + <g data-transform="boob_right" id="g2588" transform="matrix(4,0,0,4,-750.12304,-598.08667)"> <path sodipodi:nodetypes="czczsc" inkscape:connector-curvature="0" d="m 232.7832,220.84618 c 0,0 0.4464,4.52494 -1.28267,9.81182 -1.72902,5.28687 -10.19793,13.26999 -10.19793,13.26999 0,0 -2.53745,-9.20953 -1.97865,-11.40402 0.55875,-2.19451 0.93334,-3.40238 3.21651,-5.89704 2.87142,-3.13742 10.24274,-5.78075 10.24274,-5.78075 z" class="areola" id="path2586"/> </g> - <g transformVariableName="_boob_left_art_transform" id="g2592" transform="matrix(4,0,0,4,-941.71671,-583.58668)"> + <g data-transform="boob_left" id="g2592" transform="matrix(4,0,0,4,-941.71671,-583.58668)"> <path sodipodi:nodetypes="sssss" class="areola" d="m 310.12038,239.65916 c -6.9072,-0.76189 -13.8874,-5.85245 -13.92016,-10.41508 -0.0419,-5.82288 8.76879,-11.90016 16.50864,-11.56148 7.27826,0.31847 14.8736,5.06548 13.3816,12.12299 -1.49201,7.05753 -7.71129,10.76454 -15.97008,9.85357 z" id="path2590" inkscape:connector-curvature="0"/> </g> </g> <g inkscape:groupmode="layer" id="Boob_Huge_Areolae_Huge" style="display:inline;opacity:1" inkscape:label="Boob_Huge_Areolae_Huge"> - <g id="g2598" transformVariableName="_boob_right_art_transform" transform="matrix(4,0,0,4,-750.12304,-598.08667)"> + <g id="g2598" data-transform="boob_right" transform="matrix(4,0,0,4,-750.12304,-598.08667)"> <path id="path2596" class="areola" d="m 236.62959,218.29317 c 0,0 1.7243,6.58569 -0.67504,13.922 -2.39927,7.33629 -12.70181,16.77885 -12.70181,16.77885 -2.04899,-3.31055 -4.6839,-13.22984 -3.74138,-17.39573 0.94253,-4.16588 0.57641,-2.75255 3.74464,-6.21424 3.9845,-4.35363 13.37359,-7.09088 13.37359,-7.09088 z" inkscape:connector-curvature="0" sodipodi:nodetypes="czczsc"/> </g> - <g id="g2602" transformVariableName="_boob_left_art_transform" transform="matrix(4,0,0,4,-941.71671,-583.58668)"> + <g id="g2602" data-transform="boob_left" transform="matrix(4,0,0,4,-941.71671,-583.58668)"> <path inkscape:connector-curvature="0" id="path2600" d="m 310.21331,242.70695 c -8.66357,-0.95563 -17.41869,-7.34062 -17.45978,-13.06343 -0.0525,-7.30353 10.99852,-14.92615 20.70646,-14.50135 9.12899,0.39946 18.65567,6.35353 16.78428,15.20563 -1.87139,8.85212 -9.67212,13.50176 -20.03096,12.35915 z" class="areola" sodipodi:nodetypes="sssss"/> </g> </g> <g inkscape:label="Boob_Huge_Areolae_Star" style="display:inline;opacity:1" id="Boob_Huge_Areolae_Star" inkscape:groupmode="layer"> - <g transformVariableName="_boob_right_art_transform" id="g2608" transform="matrix(4,0,0,4,-750.12304,-598.08667)"> + <g data-transform="boob_right" id="g2608" transform="matrix(4,0,0,4,-750.12304,-598.08667)"> <path sodipodi:nodetypes="cccccccssc" inkscape:connector-curvature="0" d="m 234.36369,221.2914 c -5.83495,3.07543 -6.41117,3.88752 -8.98865,6.65172 3.10943,0.0163 3.09282,-0.28462 8.16273,1.84366 -7.00102,0.23835 -9.44665,2.25868 -9.44665,2.25868 0,0 -0.69998,1.91384 1.81583,11.39761 -3.75631,-5.09859 -4.6232,-9.07753 -4.6232,-9.07753 0,0 -0.7342,1.92505 -0.23957,8.04149 -1.78578,-3.48555 -1.6116,-7.85334 -1.6116,-9.31051 0,-2.16436 0.62706,-3.42478 3.74464,-6.54236 4.17315,-4.17315 11.18647,-5.26276 11.18647,-5.26276 z" class="areola" id="path2606"/> </g> - <g transformVariableName="_boob_left_art_transform" id="g2612" transform="matrix(4,0,0,4,-941.71671,-583.58668)"> + <g data-transform="boob_left" id="g2612" transform="matrix(4,0,0,4,-941.71671,-583.58668)"> <path sodipodi:nodetypes="ccccccccccc" class="areola" d="m 309.21943,229.27224 c -3.76567,1.79157 -6.84161,5.28921 -10.10232,7.39152 1.44885,-3.26388 2.80438,-7.85021 4.89355,-10.83394 -2.31674,-1.93975 -5.18388,-2.96451 -8.37065,-3.68536 3.56307,-1.07962 7.79205,-1.81135 11.55083,-1.25273 1.41528,-1.99803 2.88366,-2.69755 5.19852,-4.40935 0.47133,1.75669 1.08677,2.27498 2.38302,4.27914 4.40924,-0.57094 8.75671,0.34013 13.32809,1.37553 -4.74363,0.78623 -8.39968,1.78672 -11.63843,3.96162 1.36056,2.93262 2.11025,7.4758 2.95271,10.6874 -2.99455,-2.42622 -6.28672,-5.87702 -10.19532,-7.51383 z" id="path2610" inkscape:connector-curvature="0"/> </g> </g> <g inkscape:label="Boob_Huge_Areolae_Heart" style="display:inline;opacity:1" id="Boob_Huge_Areolae_Heart" inkscape:groupmode="layer"> - <g transformVariableName="_boob_right_art_transform" id="g2618" transform="matrix(4,0,0,4,-750.12304,-598.08667)"> + <g data-transform="boob_right" id="g2618" transform="matrix(4,0,0,4,-750.12304,-598.08667)"> <path sodipodi:nodetypes="cczcac" inkscape:connector-curvature="0" d="m 232.52122,225.53565 c 4.39417,7.66356 -5.99208,11.98476 -10.60277,20.32639 -1.91692,-2.41158 -3.13082,-10.98168 -2.2593,-14.47377 0.87152,-3.49209 1.27608,-4.34257 4.50054,-6.25453 4.9477,-1.91122 6.43637,-1.61802 8.36153,0.4019 0,0 0,1e-5 0,1e-5 z" class="areola" id="path2616"/> </g> - <g transformVariableName="_boob_left_art_transform" id="g2623" transform="matrix(4,0,0,4,-941.71671,-583.58668)"> + <g data-transform="boob_left" id="g2623" transform="matrix(4,0,0,4,-941.71671,-583.58668)"> <path sodipodi:nodetypes="czczcc" class="areola" d="m 308.00692,240.95895 c -4.20528,-2.9951 -12.71977,-16.79856 -6.01226,-22.33579 6.70751,-5.53723 9.65531,-0.0103 9.65531,-0.0103 0,0 5.61579,-5.19127 10.77973,1.06406 5.16394,6.25533 -9.37618,18.97767 -14.42277,21.28185 z" id="path2621" inkscape:connector-curvature="0"/> </g> </g> <g inkscape:groupmode="layer" id="Boob_Huge_Nipples" style="display:inline;opacity:1" inkscape:label="Boob_Huge_Nipples"> - <g id="g2307" transformVariableName="_boob_right_art_transform" transform="matrix(4,0,0,4,-750.12304,-598.08667)"> + <g id="g2307" data-transform="boob_right" transform="matrix(4,0,0,4,-750.12304,-598.08667)"> <path id="path2297" class="shadow" d="m 219.66711,231.32551 c 0,0 -2.07916,-0.84424 -1.96587,-2.50683 0.27229,-2.06527 2.87049,-4.55573 4.56939,-3.54333 0.73795,0.4953 1.19745,1.3592 1.19745,1.3592 -0.28724,2.54749 -1.44251,3.76835 -3.80097,4.69096 z" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccc"/> <path sodipodi:nodetypes="ccccc" inkscape:connector-curvature="0" d="m 219.66711,231.32551 c 0,0 -2.09128,-0.97248 -1.96587,-2.50683 0.22689,-1.88232 3.0014,-4.53764 4.56939,-3.54333 0.6399,0.45092 1.19745,1.3592 1.19745,1.3592 -0.28152,2.37691 -1.50508,3.78179 -3.80097,4.69096 z" class="areola" id="path2299"/> <path id="path2301" class="shadow" d="m 218.29586,227.4828 c 0.63254,-0.49981 1.24594,-0.4023 2.58629,-0.13128 -1.20929,-0.062 -1.73229,-0.39852 -2.58629,0.13128 z" inkscape:connector-curvature="0" sodipodi:nodetypes="ccc"/> <path id="path2303" class="shadow" d="m 219.23311,227.17234 c -0.0126,-0.30553 0.11607,-0.87173 0.80585,-0.93739 -0.78295,0.23692 -0.68828,0.58174 -0.80585,0.93739 z" inkscape:connector-curvature="0" sodipodi:nodetypes="ccc"/> <path id="path2305" class="shadow" d="m 220.87274,231.59877 c 1.83694,-1.04074 2.9183,-2.84285 2.47489,-4.27858 0.24179,0.88681 0.46243,2.78645 -2.47489,4.27858 z" inkscape:connector-curvature="0" sodipodi:nodetypes="ccc"/> </g> - <g id="g2321" transformVariableName="_boob_left_art_transform" transform="matrix(4,0,0,4,-941.71671,-583.58668)"> + <g id="g2321" data-transform="boob_left" transform="matrix(4,0,0,4,-941.71671,-583.58668)"> <path inkscape:connector-curvature="0" id="path2309" d="m 307.02662,225.35792 c -0.65912,-0.84792 -0.55031,-2.1736 -0.36852,-2.79251 0.43828,-1.66398 2.36958,-2.51043 4.05199,-2.48698 1.47529,0.0205 2.31113,0.23638 2.97306,1.55088 0.7186,0.55937 0.76617,1.51497 0.72875,1.55811 -0.19628,1.38288 -1.11197,3.36797 -3.79882,3.25712 -2.15571,0.10863 -2.89207,-0.0288 -3.58646,-1.08662 z" class="shadow" sodipodi:nodetypes="ccscccc"/> <path sodipodi:nodetypes="csscccc" class="areola" d="m 307.02662,225.35792 c -0.45016,-0.86882 -0.5452,-2.18377 -0.36852,-2.79251 0.46228,-1.59289 2.54845,-2.46893 4.05199,-2.48698 1.48227,-0.0177 2.31964,0.4407 2.97306,1.55088 0.60221,0.66517 0.7511,1.52867 0.72875,1.55811 -0.2578,1.29402 -1.17053,3.2834 -3.79882,3.25712 -2.03215,0.002 -2.83404,-0.0784 -3.58646,-1.08662 z" id="path2311" inkscape:connector-curvature="0"/> <path inkscape:connector-curvature="0" id="path2313" d="m 307.97472,221.8552 c 1.44439,-0.5616 2.8211,0.19783 3.71681,0.95003 -1.07555,-0.52478 -2.45102,-1.24397 -3.71681,-0.95003 z" class="shadow" sodipodi:nodetypes="ccc"/> @@ -1691,13 +1691,13 @@ <g inkscape:groupmode="layer" id="Boob_Huge_Areola_Piercing" style="display:inline" inkscape:label="Boob_Huge_Areola_Piercing"> <g id="g2929" transform="matrix(1.0263785,0,0,1.0263785,-8.6733354,-5.3910578)" style="fill:#c0c6c7;fill-opacity:1;stroke:none;stroke-opacity:1"/> <g id="g2931" transform="matrix(1.0228023,0,0,1.0228023,-5.1326497,-5.0109358)" style="fill:#c0c6c7;fill-opacity:1;stroke:none;stroke-opacity:1"/> - <g id="g3099" transformVariableName="_boob_left_art_transform" transform="matrix(4,0,0,4,-941.71671,-583.58668)"> + <g id="g3099" data-transform="boob_left" transform="matrix(4,0,0,4,-941.71671,-583.58668)"> <path class="shadow" sodipodi:nodetypes="accaa" id="path2933" d="m 315.07024,219.70277 c 0.0554,0.71485 -0.77245,1.51654 -1.52538,1.51654 -0.5209,-0.31622 -0.77768,-0.63239 -1.81752,-1.1162 0,-0.74876 0.67951,-1.68337 1.43634,-1.78429 0.77841,-0.1038 1.84592,0.60099 1.90656,1.38395 z" inkscape:connector-curvature="0"/> <path class="shadow" sodipodi:nodetypes="aaaaa" id="path2935" d="m 311.29057,230.82984 c 0,0.75085 -0.84636,1.58836 -1.5972,1.58836 -0.75085,0 -1.59721,-0.83751 -1.5972,-1.58836 0,-0.75084 0.84635,-1.58835 1.5972,-1.58835 0.75084,0 1.59719,0.83751 1.5972,1.58835 z" inkscape:connector-curvature="0"/> <path inkscape:connector-curvature="0" d="m 314.92621,219.70277 c 0.0577,0.68014 -0.76752,1.44396 -1.452,1.44396 -0.47354,-0.28747 -0.72935,-0.52731 -1.67466,-0.96714 0,-0.68069 0.64168,-1.61234 1.3653,-1.71638 0.71063,-0.10217 1.70063,0.5242 1.76136,1.23956 z" id="path2937" sodipodi:nodetypes="accaa" class="steel_piercing"/> <path inkscape:connector-curvature="0" d="m 311.14537,230.82984 c 0,0.68259 -0.76942,1.44396 -1.452,1.44396 -0.68259,0 -1.45201,-0.76137 -1.452,-1.44396 0,-0.68258 0.76941,-1.44395 1.452,-1.44395 0.68258,0 1.45199,0.76137 1.452,1.44395 z" id="path2941" sodipodi:nodetypes="aaaaa" class="steel_piercing"/> </g> - <g id="g3105" transformVariableName="_boob_right_art_transform" transform="matrix(4,0,0,4,-750.12304,-598.08667)"> + <g id="g3105" data-transform="boob_right" transform="matrix(4,0,0,4,-750.12304,-598.08667)"> <path class="shadow" sodipodi:nodetypes="aaaaa" id="path2939" d="m 227.38819,224.56136 c 0,0.75085 -0.84635,1.58836 -1.5972,1.58836 -0.75085,0 -1.5972,-0.83751 -1.5972,-1.58836 0,-0.75084 0.84636,-1.58835 1.5972,-1.58835 0.75084,0 1.5972,0.83751 1.5972,1.58835 z" inkscape:connector-curvature="0"/> <path class="shadow" sodipodi:nodetypes="aaaaa" id="path2943" d="m 221.66565,235.14913 c 0,0.75084 -0.84636,1.58835 -1.5972,1.58835 -0.75084,0 -1.5972,-0.83751 -1.5972,-1.58835 0,-0.75084 0.84636,-1.58835 1.5972,-1.58835 0.75084,0 1.5972,0.83751 1.5972,1.58835 z" inkscape:connector-curvature="0"/> <path inkscape:connector-curvature="0" d="m 227.24299,224.56136 c 0,0.68259 -0.76941,1.44396 -1.452,1.44396 -0.68259,0 -1.452,-0.76137 -1.452,-1.44396 0,-0.68258 0.76941,-1.44395 1.452,-1.44395 0.68258,0 1.452,0.76137 1.452,1.44395 z" id="path2945" sodipodi:nodetypes="aaaaa" class="steel_piercing"/> @@ -1705,19 +1705,19 @@ </g> </g> <g inkscape:label="Boob_Huge_Areola_Piercing_Heavy" style="display:inline" id="Boob_Huge_Areola_Piercing_Heavy" inkscape:groupmode="layer"> - <g id="g3085" transform="matrix(4,0,0,4,-941.71671,-583.58668)" transformVariableName="_boob_left_art_transform"> + <g id="g3085" transform="matrix(4,0,0,4,-941.71671,-583.58668)" data-transform="boob_left"> <path inkscape:connector-curvature="0" d="m 315.68416,222.90053 c 0,0 -0.13465,-4.47036 1.43,-5.58749 1.85611,-1.32523 5.3301,-1.17894 6.82,0.54779 1.43465,1.66269 0.96517,4.88584 -0.44,6.57352 -1.13778,1.36653 -5.17,1.3147 -5.17,1.3147 0,0 3.53534,-0.86423 4.29,-2.30073 0.61522,-1.17109 0.47784,-2.99147 -0.44,-3.94411 -1.02891,-1.06792 -3.08003,-1.33322 -4.4,-0.65735 -1.35317,0.69287 -2.09,4.05367 -2.09,4.05367 z" class="shadow" id="path2953" sodipodi:nodetypes="caaacaaac"/> <path inkscape:connector-curvature="0" d="m 305.90661,222.83383 c 0,0 0.13465,-4.47036 -1.43,-5.58749 -1.85611,-1.32523 -5.3301,-1.17893 -6.82,0.5478 -1.43464,1.66269 -0.96516,4.88583 0.44,6.57351 1.13777,1.36653 5.17,1.31471 5.17,1.31471 0,0 -3.53534,-0.86423 -4.29,-2.30073 -0.61522,-1.17109 -0.47784,-2.99147 0.44,-3.94411 1.02891,-1.06792 3.08003,-1.33323 4.4,-0.65736 1.35317,0.69287 2.09,4.05367 2.09,4.05367 z" class="shadow" id="path2955" sodipodi:nodetypes="caaacaaac"/> <path sodipodi:nodetypes="caaacaaac" id="path2959" class="steel_piercing" d="m 316.09881,222.73598 c 0,0 -0.12241,-4.06397 1.3,-5.07954 1.68738,-1.20475 4.84555,-1.07175 6.2,0.498 1.30422,1.51153 0.87742,4.44167 -0.4,5.97592 -1.03434,1.2423 -4.7,1.19519 -4.7,1.19519 0,0 3.21395,-0.78567 3.9,-2.09158 0.55929,-1.06463 0.4344,-2.71952 -0.4,-3.58555 -0.93538,-0.97084 -2.80003,-1.21202 -4,-0.59759 -1.23016,0.62988 -1.9,3.68515 -1.9,3.68515 z" inkscape:connector-curvature="0"/> <path sodipodi:nodetypes="caaacaaac" id="path2961" class="steel_piercing" d="m 305.49196,222.66929 c 0,0 0.12241,-4.06397 -1.3,-5.07954 -1.68737,-1.20475 -4.84554,-1.07176 -6.2,0.49799 -1.30423,1.51154 -0.87743,4.44168 0.4,5.97593 1.03434,1.2423 4.7,1.19518 4.7,1.19518 0,0 -3.21395,-0.78566 -3.9,-2.09157 -0.5593,-1.06463 -0.4344,-2.71952 0.4,-3.58556 0.93538,-0.97084 2.80003,-1.21202 4,-0.59759 1.23016,0.62989 1.9,3.68516 1.9,3.68516 z" inkscape:connector-curvature="0"/> </g> - <g id="g3109" transform="matrix(4,0,0,4,-750.12304,-598.08667)" transformVariableName="_boob_right_art_transform"> + <g id="g3109" transform="matrix(4,0,0,4,-750.12304,-598.08667)" data-transform="boob_right"> <path inkscape:connector-curvature="0" d="m 225.06547,228.29066 c 0,0 0.60967,-2.29861 1.54375,-2.82952 2.13513,-1.21356 5.78848,-1.60777 7.36253,0.27741 0.71838,0.86037 0.32663,2.54546 -0.475,3.32885 -1.34,1.30951 -5.58127,0.66576 -5.58127,0.66576 0,0 3.80544,0.19579 4.63127,-1.1651 0.35502,-0.58505 0.0468,-1.55455 -0.47501,-1.99731 -1.21025,-1.02692 -3.25057,-0.85339 -4.75002,-0.33287 -0.96055,0.33345 -2.25625,2.05278 -2.25625,2.05278 z" class="shadow" id="path2957" sodipodi:nodetypes="caaacaaac"/> <path sodipodi:nodetypes="caaacaaac" id="path2963" class="steel_piercing" d="m 225.48753,228.18839 c 0,0 0.55425,-2.08964 1.40341,-2.57229 1.94103,-1.10324 5.26225,-1.46162 6.69321,0.25218 0.65308,0.78216 0.29694,2.31405 -0.43182,3.02623 -1.21818,1.19047 -5.07388,0.60524 -5.07388,0.60524 0,0 3.45949,0.17799 4.21024,-1.05918 0.32275,-0.53186 0.0425,-1.41322 -0.43182,-1.81573 -1.10022,-0.93357 -2.95507,-0.77582 -4.3182,-0.30262 -0.87323,0.30313 -2.05114,1.86617 -2.05114,1.86617 z" inkscape:connector-curvature="0"/> </g> </g> <g inkscape:groupmode="layer" id="Boob_Huge_Piercing_Heavy" style="display:inline" inkscape:label="Boob_Huge_Piercing_Heavy"> - <g id="g2981" transformVariableName="_boob_left_art_transform" transform="matrix(4,0,0,4,-941.71671,-583.58668)"> + <g id="g2981" data-transform="boob_left" transform="matrix(4,0,0,4,-941.71671,-583.58668)"> <path inkscape:connector-curvature="0" d="m 305.79149,218.84986 c 0,0 -2.49411,9.18373 -0.98325,13.39981 1.04425,2.91398 3.31774,6.91285 6.40728,6.7218 3.05706,-0.18905 4.59484,-4.44702 5.47216,-7.38158 1.23461,-4.12965 -0.7356,-12.9098 -0.7356,-12.9098 0,0 0.11352,1.8255 0.16679,3.66985 -0.16929,0.006 -2.35051,-4.1e-4 -2.35051,-4.1e-4 0.0559,0.37078 -0.0172,0.52908 -0.0182,0.90408 0,0 2.10319,-0.01 2.38726,-0.0165 0.0394,2.95347 -0.12672,6.29356 -1.09131,8.44744 -0.78349,1.74932 -2.10939,3.66042 -3.89433,3.67566 -1.987,0.017 -3.50956,-2.07688 -4.40441,-4.01713 -0.94479,-2.04857 -1.13062,-5.2179 -1.1115,-8.05448 0.44876,0 0.89492,-0.0536 0.89492,-0.0536 l 0.20179,-0.91124 c 0,0 -0.63009,-0.0132 -1.08238,-0.0132 0.0399,-1.72733 0.14124,-3.46134 0.14124,-3.46134 z" class="shadow" id="path2969" sodipodi:nodetypes="caaacccccsascccccc"/> <path inkscape:connector-curvature="0" d="m 311.22782,235.59907 c 0,0 -1.85221,9.4952 -1.92044,14.30624 -0.078,5.49738 1.72993,16.40283 1.72993,16.40283 0,0 -0.37012,-9.79442 1.09665,-19.6094 -0.97824,-3.25724 -0.90614,-11.09967 -0.90614,-11.09967 z" class="shadow" id="path2971" sodipodi:nodetypes="caccc"/> <path inkscape:connector-curvature="0" d="m 310.97362,264.29827 c 0,0 -1.08607,3.59047 -0.98853,5.42648 0.0928,1.74744 1.48279,5.03598 1.48279,5.03598 0,0 1.05088,-3.32643 0.98853,-5.03598 -0.0683,-1.8739 -1.48279,-5.42648 -1.48279,-5.42648 z" class="shadow" id="path2973" sodipodi:nodetypes="cacac"/> @@ -1725,7 +1725,7 @@ <path sodipodi:nodetypes="caccc" id="path2977" class="steel_piercing" d="m 311.1816,236.99494 c 0,0 -1.68382,8.632 -1.74585,13.00567 -0.0709,4.99761 1.57266,14.91166 1.57266,14.91166 0,0 -0.33647,-8.90402 0.99696,-17.82673 -0.88931,-2.96113 -0.82377,-10.0906 -0.82377,-10.0906 z" inkscape:connector-curvature="0"/> <path sodipodi:nodetypes="cacac" id="path2979" class="steel_piercing" d="m 310.99593,264.77383 c 0,0 -0.98734,3.26407 -0.89867,4.93318 0.0844,1.58858 1.34799,4.57815 1.34799,4.57815 0,0 0.95535,-3.02401 0.89867,-4.57815 -0.0621,-1.70355 -1.34799,-4.93318 -1.34799,-4.93318 z" inkscape:connector-curvature="0"/> </g> - <g id="g2995" transformVariableName="_boob_right_art_transform" transform="matrix(4,0,0,4,-750.12304,-598.08667)"> + <g id="g2995" data-transform="boob_right" transform="matrix(4,0,0,4,-750.12304,-598.08667)"> <path inkscape:connector-curvature="0" d="m 224.04177,224.35984 c 0,0 1.84875,9.08379 0.67687,13.39983 -0.70222,2.58629 -1.73488,6.86756 -4.41084,6.72179 -2.75834,-0.15026 -3.17412,-4.68357 -3.76709,-7.3816 -0.92442,-4.20618 0.5064,-12.90978 0.5064,-12.90978 0,0 -0.0782,1.73915 -0.11483,3.58349 0.11654,0.006 1.05275,-4.1e-4 1.05275,-4.1e-4 l -0.54866,0.90407 c 0,0 -0.32127,-0.01 -0.51683,-0.0165 -0.0271,2.95346 0.0873,6.37993 0.75126,8.5338 0.53937,1.74933 1.16447,3.66321 2.68091,3.67564 1.67758,0.0137 2.41602,-2.07685 3.03204,-4.01709 0.65041,-2.04858 0.77834,-5.30427 0.76517,-8.14084 -0.30893,0 -1.87642,-0.0536 -1.87642,-0.0536 0.0596,-0.36182 0.0683,-0.46339 0.2179,-0.91125 0,0 1.33728,-0.0132 1.64865,-0.0132 -0.0275,-1.72732 -0.0972,-3.37499 -0.0972,-3.37499 z" class="shadow" id="path2983" sodipodi:nodetypes="caaacccccsascccccc"/> <path inkscape:connector-curvature="0" d="m 220.68861,241.98705 c 0,0 -1.85221,9.4952 -1.92044,14.30623 -0.078,5.49738 1.72993,16.40284 1.72993,16.40284 0,0 -0.37012,-9.79444 1.09665,-19.6094 -0.97824,-3.25724 -0.90614,-11.09967 -0.90614,-11.09967 z" class="shadow" id="path2985" sodipodi:nodetypes="caccc"/> <path inkscape:connector-curvature="0" d="m 220.43441,270.68624 c 0,0 -1.08608,3.59049 -0.98853,5.4265 0.0928,1.74744 1.48279,5.03595 1.48279,5.03595 0,0 1.05088,-3.3264 0.98853,-5.03595 -0.0683,-1.8739 -1.48279,-5.4265 -1.48279,-5.4265 z" class="shadow" id="path2987" sodipodi:nodetypes="cacac"/> @@ -1736,13 +1736,13 @@ </g> <g inkscape:label="Boob_Huge_Piercing" style="display:inline" id="Boob_Huge_Piercing" inkscape:groupmode="layer"> <g id="g2999" transform="matrix(1.0081159,0,0,1.0081159,-2.6203467,-1.6676415)" style="fill:#c0c6c7;fill-opacity:1;stroke:none;stroke-opacity:1"/> - <g id="g3009" style="fill:#c0c6c7;fill-opacity:1;stroke:none;stroke-opacity:1" transformVariableName="_boob_left_art_transform" transform="matrix(4,0,0,4,-941.71671,-583.58668)"> + <g id="g3009" style="fill:#c0c6c7;fill-opacity:1;stroke:none;stroke-opacity:1" data-transform="boob_left" transform="matrix(4,0,0,4,-941.71671,-583.58668)"> <path class="shadow" sodipodi:nodetypes="aaaaa" id="path3001" d="m 316.48783,223.10304 c 0,0.75293 -0.84427,1.5972 -1.5972,1.5972 -0.75293,0 -1.5972,-0.84427 -1.5972,-1.5972 0,-0.75293 0.84427,-1.5972 1.5972,-1.5972 0.75293,0 1.5972,0.84427 1.5972,1.5972 z" inkscape:connector-curvature="0"/> <path class="shadow" sodipodi:nodetypes="saccs" id="path3003" d="m 306.77276,224.82581 c -0.75293,0 -1.6385,-0.84541 -1.5972,-1.5972 0.046,-0.83836 1.21255,-1.57531 1.96548,-1.57531 -0.68775,1.21129 -0.7805,1.82947 -0.3682,3.17251 z" inkscape:connector-curvature="0"/> <path inkscape:connector-curvature="0" d="m 316.34263,223.10304 c 0,0.68448 -0.76752,1.452 -1.452,1.452 -0.68448,0 -1.452,-0.76752 -1.452,-1.452 0,-0.68448 0.76752,-1.452 1.452,-1.452 0.68448,0 1.452,0.76752 1.452,1.452 z" id="path3005" sodipodi:nodetypes="aaaaa" class="steel_piercing"/> <path inkscape:connector-curvature="0" d="m 306.77164,224.68061 c -0.68448,0 -1.48757,-0.76845 -1.452,-1.452 0.0399,-0.76733 1.10584,-1.452 1.79032,-1.452 -0.71906,1.10285 -0.73484,1.67672 -0.33828,2.904 z" id="path3007" sodipodi:nodetypes="saccs" class="steel_piercing"/> </g> - <g style="display:inline" id="g3019" transformVariableName="_boob_right_art_transform" transform="matrix(4,0,0,4,-750.12304,-598.08667)"> + <g style="display:inline" id="g3019" data-transform="boob_right" transform="matrix(4,0,0,4,-750.12304,-598.08667)"> <path inkscape:connector-curvature="0" d="m 224.07961,228.33118 c 0,0.74947 -0.84077,1.5972 -1.5972,1.5972 -0.75643,0 -1.5972,-0.84773 -1.5972,-1.5972 0,-0.74947 0.84077,-1.5972 1.5972,-1.5972 0.75643,0 1.5972,0.84773 1.5972,1.5972 z" id="path3011" sodipodi:nodetypes="aaaaa" class="shadow" transform="matrix(1,0,0,1.0092899,0,-2.0984812)"/> <path inkscape:connector-curvature="0" d="m 217.66199,229.81105 c -0.34466,-0.31248 -0.8444,-0.64473 -0.8444,-1.05102 0,-0.75293 0.84427,-1.5972 1.5972,-1.5972 -0.78404,0.89358 -0.83246,1.20611 -0.7528,2.64822 z" id="path3013" sodipodi:nodetypes="cscc" class="shadow" transform="matrix(1,0,0,1.0092899,0,-2.0984812)"/> <path class="steel_piercing" sodipodi:nodetypes="aaaaa" id="path3015" d="m 223.93441,228.33118 c 0,0.68134 -0.76433,1.452 -1.452,1.452 -0.68767,0 -1.452,-0.77066 -1.452,-1.452 0,-0.68133 0.76433,-1.452 1.452,-1.452 0.68767,0 1.452,0.77067 1.452,1.452 z" inkscape:connector-curvature="0" transform="matrix(1,0,0,1.0092899,0,-2.0984812)"/> @@ -1752,7 +1752,7 @@ </g> <g inkscape:label="Boob_Huge_Highlights" id="Boob_Huge_Highlights" inkscape:groupmode="layer" style="display:inline"> <g style="display:inline" inkscape:label="Boob_Huge_Highlights2" id="Boob_Huge_Highlights2" inkscape:groupmode="layer"> - <g transformVariableName="_boob_left_art_transform" id="g2663" transform="matrix(4,0,0,4,-941.71671,-583.58668)"> + <g data-transform="boob_left" id="g2663" transform="matrix(4,0,0,4,-941.71671,-583.58668)"> <path inkscape:connector-curvature="0" d="m 311.28344,209.85996 c -1.23695,2.22881 -4.15391,7.30116 -0.41757,9.282 3.52221,-2.35637 1.8912,-8.00731 0.41757,-9.282 z" class="highlight2" id="path2651" sodipodi:nodetypes="ccc"/> <path inkscape:connector-curvature="0" d="m 309.0008,230.89923 c -3.52683,3.26178 -5.76341,8.34571 -1.88762,10.3195 2.98911,-1.10062 3.7767,-5.82866 1.88762,-10.3195 z" class="highlight2" id="path2653" sodipodi:nodetypes="ccc"/> <path inkscape:connector-curvature="0" d="m 309.2774,227.50265 c -1.45195,1.21811 -0.55284,1.57513 -0.29636,2.05122 0.91423,-0.4922 1.12461,-0.75849 0.29636,-2.05122 z" class="highlight2" id="path2655" sodipodi:nodetypes="ccc"/> @@ -1761,7 +1761,7 @@ <path inkscape:connector-curvature="0" d="m 310.79064,220.21043 c -1.29574,-0.23601 -1.88877,0.15883 -2.19442,0.60489 1.134,0.2189 1.34152,0.27164 2.19442,-0.60489 z" class="highlight2" id="path2661" sodipodi:nodetypes="ccc"/> <path inkscape:connector-curvature="0" d="m 287.14784,234.24423 c -1.78019,22.27634 16.62413,23.78154 22.90192,24.02193 -23.56642,-3.77459 -22.37712,-21.24928 -22.90192,-24.02193 z" class="highlight2" id="path2673-6" sodipodi:nodetypes="ccc"/> </g> - <g transformVariableName="_boob_right_art_transform" id="g2681" transform="matrix(4,0,0,4,-750.12304,-598.08667)"> + <g data-transform="boob_right" id="g2681" transform="matrix(4,0,0,4,-750.12304,-598.08667)"> <path inkscape:connector-curvature="0" d="m 245.56304,211.91401 c -4.11836,2.60208 -12.2636,9.19756 -15.16804,10.99308 3.27443,0.0574 14.42513,-1.08898 15.16804,-10.99308 z" class="highlight2" id="path2665" sodipodi:nodetypes="ccc"/> <path inkscape:connector-curvature="0" d="m 250.43036,208.01772 c -0.95282,-0.17319 -2.05051,0.57552 -1.97909,1.35787 0.65101,0.10861 1.99182,0.29621 1.97909,-1.35787 z" class="highlight2" id="path2667" sodipodi:nodetypes="ccc"/> <path inkscape:connector-curvature="0" d="m 229.41707,228.57127 c -0.73203,-0.21484 -5.15512,0.19734 -5.63251,0.25215 0.75202,0.71167 5.58739,1.42579 5.63251,-0.25215 z" class="highlight2" id="path2671" sodipodi:nodetypes="ccc"/> @@ -1772,11 +1772,11 @@ </g> </g> <g inkscape:groupmode="layer" id="Boob_Huge_Highlights1" inkscape:label="Boob_Huge_Highlights1" style="display:inline"> - <g transformVariableName="_boob_left_art_transform" transform="matrix(4,0,0,4,-941.71671,-583.58668)" id="g2690"> + <g data-transform="boob_left" transform="matrix(4,0,0,4,-941.71671,-583.58668)" id="g2690"> <path sodipodi:nodetypes="ccc" id="path2686" class="highlight1" d="m 310.7455,213.61878 c -1.23889,2.23231 -0.62951,4.2542 0.10734,5.49919 0.8331,-1.29133 1.36861,-4.22251 -0.10734,-5.49919 z" inkscape:connector-curvature="0"/> <path sodipodi:nodetypes="ccc" id="path2688" class="highlight1" d="m 308.98735,230.89949 c -1.68861,1.7669 -1.74121,4.42131 -1.45308,5.80445 1.40005,-1.16485 2.00138,-3.93156 1.45308,-5.80445 z" inkscape:connector-curvature="0"/> </g> - <g transformVariableName="_boob_right_art_transform" id="g2694" transform="matrix(4,0,0,4,-750.12304,-598.08667)"> + <g data-transform="boob_right" id="g2694" transform="matrix(4,0,0,4,-750.12304,-598.08667)"> <path sodipodi:nodetypes="ccc" id="path2692" class="highlight1" d="m 242.78118,215.8836 c -3.18058,2.31902 -9.28242,4.77744 -11.34656,6.90425 3.63554,0.19592 9.94008,-1.84828 11.34656,-6.90425 z" inkscape:connector-curvature="0" transform="matrix(1.0060951,0,0,1.0060951,-1.9605124,-1.2116124)"/> </g> </g> @@ -1784,72 +1784,72 @@ </g> <g inkscape:groupmode="layer" id="Boob_Medium_" inkscape:label="Boob_Medium_" style="display:inline"> <g inkscape:label="Boob_Medium" style="display:inline;opacity:1" id="Boob_Medium" inkscape:groupmode="layer"> - <g transformVariableName="_boob_right_art_transform" id="g2687"> + <g data-transform="boob_right" id="g2687"> <path inkscape:connector-curvature="0" d="m 265.5598,202.06126 c -6.98215,3.2564 -12.1459,7.91148 -17.37338,13.84075 -11.32184,2.01098 -18.71223,6.38082 -25.75163,10.96125 -2.66627,10.79115 -4.63964,20.79074 2.86977,31.58189 5.0893,9.04044 12.45392,12.33466 22.45388,9.6257 10.79378,-2.60002 19.01126,-9.33031 21.77033,-22.30407 0.51484,-8.64963 10.03784,-15.80582 11.09806,-21.2787 1.24098,-5.57972 10.98028,-18.85392 3.68114,-25.19477 -5.28827,-4.59399 -12.52024,-0.43883 -18.74817,2.76795 z" class="shadow" id="path2247" sodipodi:nodetypes="ccccccccc"/> <path sodipodi:nodetypes="accccccaa" id="path2685" class="skin boob" d="m 265.5598,202.06126 c -6.58282,3.38951 -11.49746,8.12763 -17.37338,13.84075 -10.4339,2.54375 -17.83242,6.90871 -25.75163,10.96125 -2.39837,10.79115 -3.49301,20.79074 2.86977,31.58189 5.76999,8.40513 13.52235,11.33746 22.45388,9.6257 10.31257,-2.97018 18.31118,-9.79744 21.77033,-22.30407 3.23278,-7.85413 11.18689,-15.27549 12.24711,-20.74837 1.24098,-5.57972 11.28964,-22.38945 3.9905,-28.7303 -5.28827,-4.59399 -13.97865,2.56637 -20.20658,5.77315 z" inkscape:connector-curvature="0"/> </g> - <g transformVariableName="_boob_left_art_transform" id="g2693"> + <g data-transform="boob_left" id="g2693"> <path sodipodi:nodetypes="ccccc" id="path2689" class="shadow" d="m 344.93513,247.17137 c 11.50556,-18.72777 -0.99403,-25.03554 -7.30197,-37.88762 -11.45706,-9.02941 -12.82017,-9.43754 -25.94622,-9.76379 -26.26694,13.83475 -31.50169,24.95266 -28.41478,41.82961 5.19532,26.99402 48.12646,31.37297 61.66297,5.8218 z" inkscape:connector-curvature="0"/> <path inkscape:connector-curvature="0" d="m 344.93513,247.17137 c 6.85519,-11.89716 4.44093,-22.30576 -0.0687,-31.95616 -3.75098,-8.02695 -11.87524,-14.52078 -20.3528,-17.0962 -4.11529,-1.2502 -6.37048,-1.40468 -12.82672,1.40095 -25.4253,14.28793 -30.40982,25.54058 -28.41478,41.82961 5.56587,26.14704 48.78325,29.87175 61.66297,5.8218 z" class="skin boob" id="path2691" sodipodi:nodetypes="caaccc"/> </g> </g> <g inkscape:groupmode="layer" id="Boob_Medium_Areolae_Normal" style="display:inline;opacity:1" inkscape:label="Boob_Medium_Areolae_Normal"> - <g id="g1027" transformVariableName="_boob_right_art_transform"> + <g id="g1027" data-transform="boob_right"> <path id="XMLID_592_" class="areola" d="m 227.06053,224.47722 c 0,0 0.24231,2.57487 -0.69623,5.44459 -0.93851,2.86971 -5.64569,7.20295 -5.64569,7.20295 0,0 -1.26707,-4.99893 -0.96376,-6.1901 0.30329,-1.19118 0.50662,-1.84681 1.74593,-3.20091 1.5586,-1.70299 5.55975,-3.25653 5.55975,-3.25653 z" inkscape:connector-curvature="0" sodipodi:nodetypes="czczsc"/> </g> - <g id="g1036" transformVariableName="_boob_left_art_transform"> + <g id="g1036" data-transform="boob_left"> <path inkscape:connector-curvature="0" id="XMLID_593_" d="m 313.4683,223.17155 c -3.40637,-0.37574 -6.84874,-2.88621 -6.8649,-5.13633 -0.0207,-2.87162 4.32444,-5.86871 8.14144,-5.70169 3.58937,0.15706 7.3351,2.49811 6.5993,5.97861 -0.7358,3.4805 -3.80292,5.30866 -7.87584,4.85941 z" class="areola" sodipodi:nodetypes="sssss"/> </g> </g> <g inkscape:label="Boob_Medium_Areolae_Large" style="display:inline;opacity:1" id="Boob_Medium_Areolae_Large" inkscape:groupmode="layer"> - <g transformVariableName="_boob_right_art_transform" id="g2296"> + <g data-transform="boob_right" id="g2296"> <path sodipodi:nodetypes="czczsc" inkscape:connector-curvature="0" d="m 228.38636,223.74254 c 0,0 0.30094,3.19792 -0.8647,6.76203 -1.16561,3.5641 -7.01179,8.94586 -7.01179,8.94586 0,0 -1.57367,-6.20853 -1.19696,-7.68793 0.37668,-1.47941 0.62921,-2.29369 2.16839,-3.97544 1.93574,-2.11507 6.90506,-4.04452 6.90506,-4.04452 z" class="areola" id="path2293"/> </g> - <g transformVariableName="_boob_left_art_transform" id="g2313"> + <g data-transform="boob_left" id="g2313"> <path sodipodi:nodetypes="sssss" class="areola" d="m 313.28827,227.10156 c -4.61957,-0.50956 -9.28796,-3.91415 -9.30987,-6.96566 -0.028,-3.89437 5.86461,-7.95889 11.04106,-7.73238 4.86774,0.213 9.94754,3.38782 8.94968,8.10792 -0.99786,4.72011 -5.15735,7.19938 -10.68087,6.59012 z" id="path2310" inkscape:connector-curvature="0"/> </g> </g> <g inkscape:groupmode="layer" id="Boob_Medium_Areolae_Wide" style="display:inline;opacity:1" inkscape:label="Boob_Medium_Areolae_Wide"> - <g id="g2320" transformVariableName="_boob_right_art_transform"> + <g id="g2320" data-transform="boob_right"> <path id="path2318" class="areola" d="m 232.41861,221.42292 c 0,0 0.4464,4.74369 -1.28267,10.03057 -1.72902,5.28687 -10.40105,13.26999 -10.40105,13.26999 0,0 -2.33433,-9.20953 -1.77553,-11.40402 0.55875,-2.19451 0.93334,-3.40238 3.21651,-5.89704 2.87142,-3.13742 10.24274,-5.9995 10.24274,-5.9995 z" inkscape:connector-curvature="0" sodipodi:nodetypes="czczsc"/> </g> - <g id="g2324" transformVariableName="_boob_left_art_transform"> + <g id="g2324" data-transform="boob_left"> <path inkscape:connector-curvature="0" id="path2322" d="m 312.94881,231.61582 c -6.9072,-0.76189 -13.8874,-5.85245 -13.92016,-10.41508 -0.0419,-5.82288 8.76879,-11.90016 16.50864,-11.56148 7.27826,0.31847 14.8736,5.06548 13.3816,12.12299 -1.49201,7.05753 -7.71129,10.76454 -15.97008,9.85357 z" class="areola" sodipodi:nodetypes="sssss"/> </g> </g> <g inkscape:label="Boob_Medium_Areolae_Huge" style="display:inline;opacity:1" id="Boob_Medium_Areolae_Huge" inkscape:groupmode="layer"> - <g transformVariableName="_boob_right_art_transform" id="g2330"> + <g data-transform="boob_right" id="g2330"> <path sodipodi:nodetypes="czczsc" inkscape:connector-curvature="0" d="m 237.61457,219.3019 c 0,0 0.61945,6.27319 -1.77989,13.6095 -2.39927,7.33629 -14.30039,16.46948 -14.30039,16.46948 -2.73835,-3.80069 -2.90352,-12.97462 -2.1428,-17.08636 0.76072,-4.11174 0.57641,-2.75255 3.74464,-6.21424 3.9845,-4.35363 14.47844,-6.77838 14.47844,-6.77838 z" class="areola" id="path2328"/> </g> - <g transformVariableName="_boob_left_art_transform" id="g2334"> + <g data-transform="boob_left" id="g2334"> <path sodipodi:nodetypes="sssss" class="areola" d="m 312.68818,236.78493 c -8.66357,-0.95563 -17.41869,-7.34062 -17.45978,-13.06343 -0.0525,-7.30353 10.99852,-14.92615 20.70646,-14.50135 9.12899,0.39946 18.65567,6.35353 16.78428,15.20563 -1.87139,8.85212 -9.67212,13.50176 -20.03096,12.35915 z" id="path2332" inkscape:connector-curvature="0"/> </g> </g> <g inkscape:groupmode="layer" id="Boob_Medium_Areolae_Star" style="display:inline;opacity:1" inkscape:label="Boob_Medium_Areolae_Star"> - <g id="g2371" transformVariableName="_boob_right_art_transform"> + <g id="g2371" data-transform="boob_right"> <path id="path2369" class="areola" d="m 233.02542,221.55986 c -4.6859,2.14736 -5.25182,2.38871 -7.8293,5.15291 3.10943,0.0163 4.6369,0.11248 9.70681,2.24076 -8.13452,-0.21458 -10.34402,4.13038 -10.34402,4.13038 0,0 0.7366,4.80558 1.8382,10.77591 -2.3421,-2.93308 -5.27409,-9.80651 -5.27409,-9.80651 0,0 -0.57065,4.73684 -0.39999,8.20797 -1.03447,-2.46908 -1.33154,-8.50959 -1.33154,-9.96676 0,-2.16436 0.62706,-3.09666 3.74464,-6.21424 4.17315,-4.17315 9.88929,-4.52042 9.88929,-4.52042 z" inkscape:connector-curvature="0" sodipodi:nodetypes="cccccccssc"/> </g> - <g id="g2375" transformVariableName="_boob_left_art_transform"> + <g id="g2375" data-transform="boob_left"> <path inkscape:connector-curvature="0" id="path2373" d="m 311.96943,221.02224 c -3.76567,1.79157 -6.84161,5.28921 -10.10232,7.39152 1.44885,-3.26388 2.80438,-7.85021 4.89355,-10.83394 -2.31674,-1.93975 -5.18388,-2.96451 -8.37065,-3.68536 3.56307,-1.07962 7.79205,-1.81135 11.55083,-1.25273 1.41528,-1.99803 2.88366,-2.69755 5.19852,-4.40935 0.47133,1.75669 1.08677,2.27498 2.38302,4.27914 4.40924,-0.57094 8.75671,0.34013 13.32809,1.37553 -4.74363,0.78623 -8.39968,1.78672 -11.63843,3.96162 1.36056,2.93262 2.11025,7.4758 2.95271,10.6874 -2.99455,-2.42622 -6.28672,-5.87702 -10.19532,-7.51383 z" class="areola" sodipodi:nodetypes="ccccccccccc"/> </g> </g> <g inkscape:groupmode="layer" id="Boob_Medium_Areolae_Heart" style="display:inline;opacity:1" inkscape:label="Boob_Medium_Areolae_Heart"> - <g id="g2361" transformVariableName="_boob_right_art_transform"> + <g id="g2361" data-transform="boob_right"> <path id="path2359" class="areola" d="m 232.25356,226.4419 c 4.39417,7.66356 -6.67958,11.98476 -11.29027,20.32639 0,0 -2.32901,-10.92453 -1.5718,-14.47377 0.75721,-3.54924 1.27608,-4.34257 4.50054,-6.25453 4.9477,-1.91122 6.43637,-1.61802 8.36153,0.4019 0,0 0,1e-5 0,1e-5 z" inkscape:connector-curvature="0" sodipodi:nodetypes="cczcac"/> </g> - <g id="g2365" transformVariableName="_boob_left_art_transform"> + <g id="g2365" data-transform="boob_left"> <path inkscape:connector-curvature="0" id="path2363" d="m 310.81942,233.08395 c -4.20528,-2.9951 -12.71977,-16.79856 -6.01226,-22.33579 6.70751,-5.53723 9.65531,-0.0103 9.65531,-0.0103 0,0 5.61579,-5.19127 10.77973,1.06406 5.16394,6.25533 -9.37618,18.97767 -14.42277,21.28185 z" class="areola" sodipodi:nodetypes="czczcc"/> </g> </g> <g inkscape:label="Boob_Medium_Nipples" style="display:inline;opacity:1" id="Boob_Medium_Nipples" inkscape:groupmode="layer"> - <g transformVariableName="_boob_right_art_transform" id="g2294"> + <g data-transform="boob_right" id="g2294"> <path sodipodi:nodetypes="ccccc" inkscape:connector-curvature="0" d="m 219.66711,231.32551 c 0,0 -2.07916,-0.84424 -1.96587,-2.50683 0.27229,-2.06527 2.87049,-4.55573 4.56939,-3.54333 0.73795,0.4953 1.19745,1.3592 1.19745,1.3592 -0.28724,2.54749 -1.44251,3.76835 -3.80097,4.69096 z" class="shadow" id="path2283"/> <path id="path2285" class="areola" d="m 219.66711,231.32551 c 0,0 -2.09128,-0.97248 -1.96587,-2.50683 0.22689,-1.88232 3.0014,-4.53764 4.56939,-3.54333 0.6399,0.45092 1.19745,1.3592 1.19745,1.3592 -0.28152,2.37691 -1.50508,3.78179 -3.80097,4.69096 z" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccc"/> <path sodipodi:nodetypes="ccc" inkscape:connector-curvature="0" d="m 218.29586,227.4828 c 0.63254,-0.49981 1.24594,-0.4023 2.58629,-0.13128 -1.20929,-0.062 -1.73229,-0.39852 -2.58629,0.13128 z" class="shadow" id="path2288"/> <path sodipodi:nodetypes="ccc" inkscape:connector-curvature="0" d="m 219.23311,227.17234 c -0.0126,-0.30553 0.11607,-0.87173 0.80585,-0.93739 -0.78295,0.23692 -0.68828,0.58174 -0.80585,0.93739 z" class="shadow" id="path2290"/> <path sodipodi:nodetypes="ccc" inkscape:connector-curvature="0" d="m 220.87274,231.59877 c 1.83694,-1.04074 2.9183,-2.84285 2.47489,-4.27858 0.24179,0.88681 0.46243,2.78645 -2.47489,4.27858 z" class="shadow" id="path2292"/> </g> - <g transformVariableName="_boob_left_art_transform" id="g2310"> + <g data-transform="boob_left" id="g2310"> <path sodipodi:nodetypes="ccscccc" class="shadow" d="m 309.81086,216.32021 c -0.65912,-0.84792 -0.55031,-2.1736 -0.36852,-2.79251 0.43828,-1.66398 2.36958,-2.51043 4.05199,-2.48698 1.47529,0.0205 2.31113,0.23638 2.97306,1.55088 0.7186,0.55937 0.76617,1.51497 0.72875,1.55811 -0.19628,1.38288 -1.11197,3.36797 -3.79882,3.25712 -2.15571,0.10863 -2.89207,-0.0288 -3.58646,-1.08662 z" id="path2298" inkscape:connector-curvature="0"/> <path inkscape:connector-curvature="0" id="path2300" d="m 309.81086,216.32021 c -0.45016,-0.86882 -0.5452,-2.18377 -0.36852,-2.79251 0.46228,-1.59289 2.54845,-2.46893 4.05199,-2.48698 1.48227,-0.0177 2.31964,0.4407 2.97306,1.55088 0.60221,0.66517 0.7511,1.52867 0.72875,1.55811 -0.2578,1.29402 -1.17053,3.2834 -3.79882,3.25712 -2.03215,0.002 -2.83404,-0.0784 -3.58646,-1.08662 z" class="areola" sodipodi:nodetypes="csscccc"/> <path sodipodi:nodetypes="ccc" class="shadow" d="m 310.75896,212.81749 c 1.44439,-0.5616 2.8211,0.19783 3.71681,0.95003 -1.07555,-0.52478 -2.45102,-1.24397 -3.71681,-0.95003 z" id="path2302" inkscape:connector-curvature="0"/> @@ -1860,13 +1860,13 @@ </g> <g style="display:inline" inkscape:label="Boob_Medium_Piercings_" id="Boob_Medium_Piercings_" inkscape:groupmode="layer"> <g inkscape:label="Boob_Medium_Areola_Piercing" style="display:inline" id="Boob_Medium_Areola_Piercing" inkscape:groupmode="layer"> - <g id="g2527" transformVariableName="_boob_left_art_transform"> + <g id="g2527" data-transform="boob_left"> <path inkscape:connector-curvature="0" d="m 318.02336,210.86274 c -5e-5,0.72098 -0.77245,1.52498 -1.52538,1.52498 -0.5209,-0.31798 -0.64486,-0.93444 -1.6847,-1.42095 0,-0.75293 0.8338,-1.69079 1.61288,-1.70123 0.75078,-0.0101 1.59725,0.84217 1.5972,1.5972 z" id="path2736" sodipodi:nodetypes="accaa" class="shadow"/> <path inkscape:connector-curvature="0" d="m 312.43119,221.98893 c 0,0.75503 -0.84635,1.5972 -1.5972,1.5972 -0.75085,0 -1.5972,-0.84217 -1.5972,-1.5972 0,-0.75502 0.84635,-1.5972 1.5972,-1.5972 0.75085,0 1.5972,0.84218 1.5972,1.5972 z" id="path2738" sodipodi:nodetypes="aaaaa" class="shadow"/> <path class="steel_piercing" sodipodi:nodetypes="accaa" id="path2740" d="m 317.87933,210.86274 c 0,0.68639 -0.76752,1.452 -1.452,1.452 -0.47354,-0.28907 -0.59653,-0.82878 -1.54184,-1.27106 0,-0.68448 0.79549,-1.62217 1.54184,-1.63294 0.68251,-0.01 1.452,0.76561 1.452,1.452 z" inkscape:connector-curvature="0"/> <path class="steel_piercing" sodipodi:nodetypes="aaaaa" id="path2744" d="m 312.28599,221.98893 c 0,0.68639 -0.76941,1.452 -1.452,1.452 -0.68259,0 -1.452,-0.76561 -1.452,-1.452 0,-0.68639 0.76941,-1.452 1.452,-1.452 0.68259,0 1.452,0.76561 1.452,1.452 z" inkscape:connector-curvature="0"/> </g> - <g id="g2533" transformVariableName="_boob_right_art_transform"> + <g id="g2533" data-transform="boob_right"> <path inkscape:connector-curvature="0" d="m 227.48194,224.84564 c 0,0.75503 -0.84635,1.5972 -1.5972,1.5972 -0.75084,0 -1.5972,-0.84217 -1.5972,-1.5972 0,-0.75503 0.84636,-1.5972 1.5972,-1.5972 0.75085,0 1.5972,0.84217 1.5972,1.5972 z" id="path2742" sodipodi:nodetypes="aaaaa" class="shadow"/> <path inkscape:connector-curvature="0" d="m 221.3219,235.74376 c 0,0.75502 -0.84635,1.5972 -1.5972,1.5972 -0.75084,0 -1.5972,-0.84218 -1.5972,-1.5972 0,-0.75503 0.84636,-1.5972 1.5972,-1.5972 0.75085,0 1.5972,0.84217 1.5972,1.5972 z" id="path2746" sodipodi:nodetypes="aaaaa" class="shadow"/> <path class="steel_piercing" sodipodi:nodetypes="aaaaa" id="path2748" d="m 227.33674,224.84564 c 0,0.68639 -0.76941,1.452 -1.452,1.452 -0.68258,0 -1.452,-0.76561 -1.452,-1.452 0,-0.68639 0.76942,-1.452 1.452,-1.452 0.68259,0 1.452,0.76561 1.452,1.452 z" inkscape:connector-curvature="0"/> @@ -1874,19 +1874,19 @@ </g> </g> <g inkscape:groupmode="layer" id="Boob_Medium_Areola_Piercing_Heavy" style="display:inline" inkscape:label="Boob_Medium_Areola_Piercing_Heavy"> - <g id="g2507" transformVariableName="_boob_left_art_transform"> + <g id="g2507" data-transform="boob_left"> <path sodipodi:nodetypes="caaacaaac" id="path2757" class="shadow" d="m 318.90291,214.58803 c 0,0 -0.13465,-4.47036 1.43,-5.58749 1.85611,-1.32523 5.3301,-1.17893 6.82,0.54779 1.43464,1.66269 0.96516,4.88585 -0.44,6.57352 -1.13778,1.36653 -5.17,1.3147 -5.17,1.3147 0,0 3.53534,-0.86423 4.29,-2.30073 0.61522,-1.17109 0.47784,-2.99147 -0.44,-3.94411 -1.02892,-1.06792 -3.08003,-1.33322 -4.4,-0.65735 -1.35318,0.69288 -2.09,4.05367 -2.09,4.05367 z" inkscape:connector-curvature="0"/> <path sodipodi:nodetypes="caaacaaac" id="path2761" class="shadow" d="m 308.90661,215.70883 c 0,0 0.13465,-4.47036 -1.43,-5.58749 -1.85611,-1.32523 -5.3301,-1.17893 -6.82,0.5478 -1.43465,1.66269 -0.96516,4.88583 0.44,6.57351 1.13778,1.36653 5.17,1.31471 5.17,1.31471 0,0 -3.53534,-0.86423 -4.29,-2.30073 -0.61522,-1.1711 -0.47784,-2.99148 0.44,-3.94411 1.02892,-1.06793 3.08003,-1.33323 4.4,-0.65736 1.35317,0.69287 2.09,4.05367 2.09,4.05367 z" inkscape:connector-curvature="0"/> <path inkscape:connector-curvature="0" d="m 319.31756,214.42348 c 0,0 -0.12241,-4.06396 1.3,-5.07954 1.68737,-1.20474 4.84554,-1.07175 6.2,0.498 1.30422,1.51154 0.87742,4.44167 -0.4,5.97592 -1.03434,1.24231 -4.7,1.19519 -4.7,1.19519 0,0 3.21394,-0.78566 3.9,-2.09158 0.55929,-1.06462 0.4344,-2.71951 -0.4,-3.58555 -0.93538,-0.97084 -2.80003,-1.21202 -4,-0.59759 -1.23016,0.62989 -1.9,3.68515 -1.9,3.68515 z" class="steel_piercing" id="path2767" sodipodi:nodetypes="caaacaaac"/> <path inkscape:connector-curvature="0" d="m 308.49196,215.54429 c 0,0 0.12241,-4.06397 -1.3,-5.07954 -1.68737,-1.20476 -4.84554,-1.07176 -6.2,0.49799 -1.30422,1.51153 -0.87742,4.44167 0.4,5.97593 1.03434,1.24229 4.7,1.19518 4.7,1.19518 0,0 -3.21395,-0.78566 -3.9,-2.09157 -0.55929,-1.06463 -0.4344,-2.71952 0.4,-3.58556 0.93538,-0.97083 2.80003,-1.21202 4,-0.59759 1.23016,0.62988 1.9,3.68516 1.9,3.68516 z" class="steel_piercing" id="path2769" sodipodi:nodetypes="caaacaaac"/> </g> - <g id="g2512" transformVariableName="_boob_right_art_transform"> + <g id="g2512" data-transform="boob_right"> <path sodipodi:nodetypes="caaacaaac" id="path2764" class="shadow" d="m 224.55987,227.39942 c 0,0 0.60967,-2.2986 1.54375,-2.82952 2.13513,-1.21356 5.78847,-1.60777 7.36253,0.27741 0.71838,0.86037 0.32663,2.54545 -0.475,3.32885 -1.34,1.30951 -5.58127,0.66576 -5.58127,0.66576 0,0 3.80544,0.19579 4.63127,-1.1651 0.35502,-0.58505 0.0468,-1.55454 -0.47501,-1.99731 -1.21025,-1.02692 -3.25058,-0.85339 -4.75002,-0.33287 -0.96055,0.33344 -2.25625,2.05278 -2.25625,2.05278 z" inkscape:connector-curvature="0"/> <path inkscape:connector-curvature="0" d="m 224.98193,227.29715 c 0,0 0.55424,-2.08964 1.40341,-2.57229 1.94103,-1.10324 5.26225,-1.46161 6.69321,0.25218 0.65307,0.78216 0.29693,2.31406 -0.43182,3.02623 -1.21818,1.19048 -5.07388,0.60524 -5.07388,0.60524 0,0 3.45948,0.178 4.21024,-1.05918 0.32274,-0.53186 0.0425,-1.41322 -0.43182,-1.81573 -1.10023,-0.93357 -2.95507,-0.77582 -4.3182,-0.30262 -0.87323,0.30313 -2.05114,1.86617 -2.05114,1.86617 z" class="steel_piercing" id="path2771" sodipodi:nodetypes="caaacaaac"/> </g> </g> <g inkscape:label="Boob_Medium_Piercing_Heavy" style="display:inline" id="Boob_Medium_Piercing_Heavy" inkscape:groupmode="layer"> - <g transformVariableName="_boob_left_art_transform" id="g2789"> + <g data-transform="boob_left" id="g2789"> <path sodipodi:nodetypes="caaacccccsascccccc" id="path2777" class="shadow" d="m 308.53153,209.94473 c 0,0 -2.49411,9.18374 -0.98325,13.39981 1.04425,2.91398 3.31774,6.91285 6.40728,6.7218 3.05706,-0.18904 4.59484,-4.44702 5.47216,-7.38158 1.23461,-4.12965 -0.7356,-12.9098 -0.7356,-12.9098 0,0 0.11352,1.8255 0.16679,3.66985 -0.16929,0.006 -2.35051,-4.1e-4 -2.35051,-4.1e-4 0.0559,0.37078 -0.0172,0.52908 -0.0182,0.90408 0,0 2.10319,-0.01 2.38726,-0.0165 0.0394,2.95347 -0.12672,6.29356 -1.09131,8.44744 -0.78349,1.74932 -2.10939,3.66042 -3.89433,3.67566 -1.987,0.017 -3.50956,-2.07688 -4.40441,-4.01713 -0.94479,-2.04857 -1.13062,-5.2179 -1.1115,-8.05448 0.44876,0 0.89492,-0.0536 0.89492,-0.0536 l 0.20179,-0.91124 c 0,0 -0.63009,-0.0132 -1.08238,-0.0132 0.0399,-1.72733 0.14124,-3.46134 0.14124,-3.46134 z" inkscape:connector-curvature="0"/> <path sodipodi:nodetypes="caccc" id="path2779" class="shadow" d="m 313.96786,226.69394 c 0,0 -1.85221,9.4952 -1.92044,14.30624 -0.078,5.49738 1.72993,16.40283 1.72993,16.40283 0,0 -0.37012,-9.79442 1.09665,-19.6094 -0.97824,-3.25724 -0.90614,-11.09967 -0.90614,-11.09967 z" inkscape:connector-curvature="0"/> <path sodipodi:nodetypes="cacac" id="path2781" class="shadow" d="m 313.71366,255.39314 c 0,0 -1.08607,3.59047 -0.98853,5.42648 0.0928,1.74745 1.48279,5.03598 1.48279,5.03598 0,0 1.05088,-3.32642 0.98853,-5.03598 -0.0683,-1.87389 -1.48279,-5.42648 -1.48279,-5.42648 z" inkscape:connector-curvature="0"/> @@ -1894,7 +1894,7 @@ <path inkscape:connector-curvature="0" d="m 313.92164,228.08981 c 0,0 -1.68382,8.632 -1.74585,13.00567 -0.0709,4.99762 1.57266,14.91166 1.57266,14.91166 0,0 -0.33647,-8.90402 0.99696,-17.82673 -0.88931,-2.96113 -0.82377,-10.0906 -0.82377,-10.0906 z" class="steel_piercing" id="path2785" sodipodi:nodetypes="caccc"/> <path inkscape:connector-curvature="0" d="m 313.73597,255.8687 c 0,0 -0.98734,3.26408 -0.89867,4.93318 0.0844,1.58858 1.34799,4.57815 1.34799,4.57815 0,0 0.95535,-3.02401 0.89867,-4.57815 -0.0621,-1.70355 -1.34799,-4.93318 -1.34799,-4.93318 z" class="steel_piercing" id="path2787" sodipodi:nodetypes="cacac"/> </g> - <g transformVariableName="_boob_right_art_transform" id="g2803"> + <g data-transform="boob_right" id="g2803"> <path sodipodi:nodetypes="caaacccccsascccccc" id="path2791" class="shadow" d="m 224.22146,224.11765 c 0,0 1.84875,9.08379 0.67687,13.39983 -0.70222,2.58629 -1.73488,6.86756 -4.41084,6.72179 -2.75834,-0.15025 -3.17412,-4.68356 -3.76709,-7.3816 -0.92442,-4.20618 0.5064,-12.90978 0.5064,-12.90978 0,0 -0.0782,1.73915 -0.11483,3.58349 0.11654,0.006 1.05275,-4.1e-4 1.05275,-4.1e-4 l -0.54866,0.90407 c 0,0 -0.32127,-0.01 -0.51683,-0.0165 -0.0271,2.95346 0.0873,6.37993 0.75126,8.5338 0.53937,1.74933 1.16447,3.66322 2.68091,3.67564 1.67758,0.0137 2.41602,-2.07685 3.03204,-4.01709 0.65041,-2.04858 0.77834,-5.30427 0.76517,-8.14084 -0.30893,0 -1.87642,-0.0536 -1.87642,-0.0536 0.0596,-0.36182 0.0683,-0.46339 0.2179,-0.91125 0,0 1.33728,-0.0132 1.64865,-0.0132 -0.0275,-1.72732 -0.0972,-3.37499 -0.0972,-3.37499 z" inkscape:connector-curvature="0"/> <path sodipodi:nodetypes="caccc" id="path2793" class="shadow" d="m 220.8683,241.74486 c 0,0 -1.85221,9.4952 -1.92044,14.30623 -0.078,5.49739 1.72993,16.40284 1.72993,16.40284 0,0 -0.37012,-9.79444 1.09665,-19.6094 -0.97824,-3.25724 -0.90614,-11.09967 -0.90614,-11.09967 z" inkscape:connector-curvature="0"/> <path sodipodi:nodetypes="cacac" id="path2795" class="shadow" d="m 220.6141,270.44405 c 0,0 -1.08607,3.59049 -0.98853,5.4265 0.0928,1.74744 1.48279,5.03595 1.48279,5.03595 0,0 1.05088,-3.3264 0.98853,-5.03595 -0.0683,-1.8739 -1.48279,-5.4265 -1.48279,-5.4265 z" inkscape:connector-curvature="0"/> @@ -1905,13 +1905,13 @@ </g> <g inkscape:groupmode="layer" id="Boob_Medium_Piercing" style="display:inline" inkscape:label="Boob_Medium_Piercing"> <g style="fill:#c0c6c7;fill-opacity:1;stroke:none;stroke-opacity:1" transform="matrix(1.0081159,0,0,1.0081159,-2.6203467,-1.6676415)" id="g2807"/> - <g transformVariableName="_boob_left_art_transform" style="fill:#c0c6c7;fill-opacity:1;stroke:none;stroke-opacity:1" id="g2817"> + <g data-transform="boob_left" style="fill:#c0c6c7;fill-opacity:1;stroke:none;stroke-opacity:1" id="g2817"> <path inkscape:connector-curvature="0" d="m 319.36283,214.04054 c 0,0.74947 -0.84077,1.5972 -1.5972,1.5972 -0.75643,0 -1.5972,-0.84773 -1.5972,-1.5972 0,-0.74947 0.84077,-1.5972 1.5972,-1.5972 0.75643,0 1.5972,0.84773 1.5972,1.5972 z" id="path2809" sodipodi:nodetypes="aaaaa" class="shadow"/> <path inkscape:connector-curvature="0" d="m 309.64776,215.76331 c -0.75293,0 -1.63873,-0.84886 -1.5972,-1.5972 0.0463,-0.83366 1.21255,-1.57531 1.96548,-1.57531 -0.68775,1.21129 -0.7805,1.82947 -0.3682,3.17251 z" id="path2811" sodipodi:nodetypes="saccs" class="shadow"/> <path class="steel_piercing" sodipodi:nodetypes="aaaaa" id="path2813" d="m 319.21763,214.04054 c 0,0.68133 -0.76433,1.452 -1.452,1.452 -0.68767,0 -1.452,-0.77067 -1.452,-1.452 0,-0.68134 0.76433,-1.452 1.452,-1.452 0.68767,0 1.452,0.77066 1.452,1.452 z" inkscape:connector-curvature="0"/> <path class="steel_piercing" sodipodi:nodetypes="saccs" id="path2815" d="m 309.64664,215.61811 c -0.68448,0 -1.48776,-0.77158 -1.452,-1.452 0.0401,-0.76308 1.10584,-1.452 1.79032,-1.452 -0.71906,1.10285 -0.73484,1.67672 -0.33828,2.904 z" inkscape:connector-curvature="0"/> </g> - <g transformVariableName="_boob_right_art_transform" id="g2827" style="display:inline"> + <g data-transform="boob_right" id="g2827" style="display:inline"> <path transform="matrix(1,0,0,1.0092899,0,-2.0984812)" class="shadow" sodipodi:nodetypes="aaaaa" id="path2819" d="m 224.20461,228.08348 c 0,0.74947 -0.84077,1.5972 -1.5972,1.5972 -0.75643,0 -1.5972,-0.84773 -1.5972,-1.5972 0,-0.74947 0.84077,-1.5972 1.5972,-1.5972 0.75643,0 1.5972,0.84773 1.5972,1.5972 z" inkscape:connector-curvature="0"/> <path transform="matrix(1,0,0,1.0092899,0,-2.0984812)" class="shadow" sodipodi:nodetypes="cscc" id="path2821" d="m 217.78699,229.56335 c -0.34466,-0.31248 -0.8444,-0.64473 -0.8444,-1.05102 0,-0.75293 0.84427,-1.5972 1.5972,-1.5972 -0.78404,0.89358 -0.83246,1.20611 -0.7528,2.64822 z" inkscape:connector-curvature="0"/> <path transform="matrix(1,0,0,1.0092899,0,-2.0984812)" inkscape:connector-curvature="0" d="m 224.05941,228.08348 c 0,0.68133 -0.76433,1.452 -1.452,1.452 -0.68767,0 -1.452,-0.77067 -1.452,-1.452 0,-0.68134 0.76433,-1.452 1.452,-1.452 0.68767,0 1.452,0.77066 1.452,1.452 z" id="path2823" sodipodi:nodetypes="aaaaa" class="steel_piercing"/> @@ -1921,7 +1921,7 @@ </g> <g inkscape:groupmode="layer" id="Boob_Medium_Highlights" inkscape:label="Boob_Medium_Highlights" style="display:inline"> <g inkscape:groupmode="layer" id="Boob_Medium_Highlights2" inkscape:label="Boob_Medium_Highlights2" style="display:inline"> - <g id="g3014" transformVariableName="_boob_left_art_transform"> + <g id="g3014" data-transform="boob_left"> <path sodipodi:nodetypes="ccc" id="XMLID_511_-1-8-0-3-9" class="highlight2" d="m 321.76732,202.98942 c -2.24758,1.20251 -7.44827,3.88396 -5.38213,7.57381 4.23715,-0.071 5.92957,-5.70386 5.38213,-7.57381 z" inkscape:connector-curvature="0"/> <path sodipodi:nodetypes="ccc" id="XMLID_511_-1-8-0-3-9-7" class="highlight2" d="m 312.09439,222.06039 c -3.52683,3.26178 -5.76341,8.34571 -1.88762,10.3195 2.98911,-1.10062 3.7767,-5.82866 1.88762,-10.3195 z" inkscape:connector-curvature="0"/> <path sodipodi:nodetypes="ccc" id="XMLID_511_-1-8-0-3-9-7-4" class="highlight2" d="m 312.37099,218.66381 c -1.45195,1.21811 -0.55284,1.57513 -0.29636,2.05122 0.91423,-0.4922 1.12461,-0.75849 0.29636,-2.05122 z" inkscape:connector-curvature="0"/> @@ -1929,7 +1929,7 @@ <path sodipodi:nodetypes="ccc" id="XMLID_511_-1-8-0-3-9-7-4-2" class="highlight2" d="m 314.01066,214.12617 c -1.11294,-1.53405 -2.19421,-0.93805 -2.68716,-0.71571 0.55046,0.56081 1.587,0.71901 2.68716,0.71571 z" inkscape:connector-curvature="0"/> <path sodipodi:nodetypes="ccc" id="XMLID_511_-1-8-0-3-9-7-4-2-1" class="highlight2" d="m 313.88423,211.37159 c -1.29574,-0.23601 -1.88877,0.15883 -2.19442,0.60489 1.134,0.2189 1.34152,0.27164 2.19442,-0.60489 z" inkscape:connector-curvature="0"/> </g> - <g id="g3024" transformVariableName="_boob_right_art_transform"> + <g id="g3024" data-transform="boob_right"> <path sodipodi:nodetypes="ccc" id="XMLID_511_-1-8-0-3-9-7-7" class="highlight2" d="m 247.9062,221.14042 c -7.62159,-1.9871 -15.09403,5.90489 -17.77314,7.66238 4.07679,1.14519 17.22608,2.90775 17.77314,-7.66238 z" inkscape:connector-curvature="0"/> <path sodipodi:nodetypes="ccc" id="XMLID_511_-1-8-0-3-9-7-7-5" class="highlight2" d="m 255.78198,212.79897 c -0.95282,-0.17319 -2.05051,0.57552 -1.97909,1.35787 0.65101,0.10861 1.99182,0.29621 1.97909,-1.35787 z" inkscape:connector-curvature="0"/> <path sodipodi:nodetypes="ccc" id="XMLID_511_-1-8-0-3-9-7-7-5-1-0-9" class="highlight2" d="m 229.41707,228.57127 c -0.73203,-0.21484 -5.15512,0.19734 -5.63251,0.25215 0.75202,0.71167 5.58739,1.42579 5.63251,-0.25215 z" inkscape:connector-curvature="0"/> @@ -1940,11 +1940,11 @@ </g> </g> <g style="display:inline" inkscape:label="Boob_Medium_Highlights1" id="Boob_Medium_Highlights1" inkscape:groupmode="layer"> - <g id="g2210" transform="matrix(1.0060951,0,0,1.0060951,-1.9605124,-1.2116124)" transformVariableName="_boob_left_art_transform"> + <g id="g2210" transform="matrix(1.0060951,0,0,1.0060951,-1.9605124,-1.2116124)" data-transform="boob_left"> <path inkscape:connector-curvature="0" d="m 319.27783,205.85656 c -2.25111,1.2044 -2.83496,3.23381 -2.89058,4.67945 1.40005,-0.6336 3.43888,-2.80656 2.89058,-4.67945 z" class="highlight1" id="path1139" sodipodi:nodetypes="ccc"/> <path inkscape:connector-curvature="0" d="m 312.08094,222.06065 c -1.68861,1.7669 -1.74121,4.42131 -1.45308,5.80445 1.40005,-1.16485 2.00138,-3.93156 1.45308,-5.80445 z" class="highlight1" id="path1141" sodipodi:nodetypes="ccc"/> </g> - <g id="g2992" transformVariableName="_boob_right_art_transform"> + <g id="g2992" data-transform="boob_right"> <path transform="matrix(1.0060951,0,0,1.0060951,-1.9605124,-1.2116124)" inkscape:connector-curvature="0" d="m 241.75459,224.35338 c -4.7273,0.75979 -7.83647,2.53916 -10.64479,3.98691 4.08319,1.14699 9.56562,1.06857 10.64479,-3.98691 z" class="highlight1" id="path1143" sodipodi:nodetypes="ccc"/> </g> </g> @@ -1952,72 +1952,72 @@ </g> <g style="display:inline" inkscape:label="Boob_Small_" id="Boob_Small_" inkscape:groupmode="layer"> <g inkscape:groupmode="layer" id="Boob_Small" style="display:inline;opacity:1" inkscape:label="Boob_Small"> - <g id="g2754" transformVariableName="_boob_right_art_transform"> + <g id="g2754" data-transform="boob_right"> <path sodipodi:nodetypes="ccccccc" id="path2750" class="shadow" d="m 258.4635,206.70525 c -2.43693,2.43693 -11.69974,10.96496 -13.78161,16.78224 -7.98808,4.18336 -12.04016,9.22946 -16.46667,14.18272 0.43705,8.71501 1.70553,16.51029 9.57142,22.68835 5.76096,5.49343 12.38835,5.57452 18.88215,1.82583 5.22936,-5.97715 7.46563,-9.46914 13.85527,-23.053 -9.9785,-11.21563 7.18836,-22.98696 -12.06056,-32.42614 z" inkscape:connector-curvature="0"/> <path inkscape:connector-curvature="0" d="m 258.4635,206.70525 c -2.51112,2.51112 -10.78183,11.16972 -13.78161,16.78224 -7.11937,4.34266 -11.56357,9.31685 -16.46667,14.18272 0.77061,8.54923 2.31908,16.20536 9.57142,22.68835 6.25108,4.85755 12.67805,5.19866 18.88215,1.82583 6.92903,-4.62954 11.03703,-12.07965 15.29277,-23.053 -0.9345,-14.31756 6.59712,-27.64388 -13.49806,-32.42614 z" class="skin boob" id="path2752" sodipodi:nodetypes="ccccccc"/> </g> - <g id="g2762" transformVariableName="_boob_left_art_transform"> + <g id="g2762" data-transform="boob_left"> <path inkscape:connector-curvature="0" d="m 343.18566,248.84738 c 6.61502,-9.96293 1.24605,-23.02347 -3.51192,-32.52403 -4.32357,-4.32357 -19.56457,-7.69007 -30.17045,-7.95661 -8.8142,9.37784 -15.40168,21.99318 -18.70132,35.53493 4.9837,22.57548 41.64172,26.17839 52.38369,4.94571 z" class="shadow" id="path2756" sodipodi:nodetypes="ccccc"/> <path sodipodi:nodetypes="ccccc" id="path2760" class="skin boob" d="m 343.18566,248.84738 c 5.82359,-10.10683 3.21095,-23.94463 -2.82442,-32.52403 -2.73692,-4.74049 -22.03284,-11.71831 -31.42045,-7.95661 -9.28671,7.38783 -19.83364,21.69713 -18.13882,35.53493 4.7283,22.21233 41.44215,25.37653 52.38369,4.94571 z" inkscape:connector-curvature="0"/> </g> </g> <g inkscape:label="Boob_Small_Areolae_Normal" style="display:inline;opacity:1" id="Boob_Small_Areolae_Normal" inkscape:groupmode="layer"> - <g transformVariableName="_boob_right_art_transform" id="g2430"> + <g data-transform="boob_right" id="g2430"> <path sodipodi:nodetypes="czczsc" inkscape:connector-curvature="0" d="m 235.30274,231.17264 c 0,0 0.24231,2.57487 -0.69623,5.44459 -0.93851,2.86971 -5.64569,7.20295 -5.64569,7.20295 0,0 -1.26707,-4.99893 -0.96376,-6.1901 0.30329,-1.19118 0.50662,-1.84681 1.74593,-3.20091 1.5586,-1.70299 5.55975,-3.25653 5.55975,-3.25653 z" class="areola" id="path2428"/> </g> - <g transformVariableName="_boob_left_art_transform" id="g2434"> + <g data-transform="boob_left" id="g2434"> <path sodipodi:nodetypes="sssss" class="areola" d="m 316.0933,235.60905 c -3.40637,-0.37574 -6.84874,-2.88621 -6.8649,-5.13633 -0.0207,-2.87162 4.32444,-5.86871 8.14144,-5.70169 3.58937,0.15706 7.3351,2.49811 6.5993,5.97861 -0.7358,3.4805 -3.80292,5.30866 -7.87584,4.85941 z" id="path2432" inkscape:connector-curvature="0"/> </g> </g> <g inkscape:groupmode="layer" id="Boob_Small_Areolae_Large" style="display:inline;opacity:1" inkscape:label="Boob_Small_Areolae_Large"> - <g id="g2440" transformVariableName="_boob_right_art_transform"> + <g id="g2440" data-transform="boob_right"> <path id="path2438" class="areola" d="m 237.2031,229.73085 c 0,0 0.30094,3.19792 -0.8647,6.76203 -1.16561,3.5641 -7.01179,8.94586 -7.01179,8.94586 0,0 -1.57367,-6.20853 -1.19696,-7.68793 0.37668,-1.47941 0.62921,-2.29369 2.16839,-3.97544 1.93574,-2.11507 6.90506,-4.04452 6.90506,-4.04452 z" inkscape:connector-curvature="0" sodipodi:nodetypes="czczsc"/> </g> - <g id="g2444" transformVariableName="_boob_left_art_transform"> + <g id="g2444" data-transform="boob_left"> <path inkscape:connector-curvature="0" id="path2442" d="m 315.47577,238.97656 c -4.61957,-0.50956 -9.28796,-3.91415 -9.30987,-6.96566 -0.028,-3.89437 5.86461,-7.95889 11.04106,-7.73238 4.86774,0.213 9.94754,3.38782 8.94968,8.10792 -0.99786,4.72011 -5.15735,7.19938 -10.68087,6.59012 z" class="areola" sodipodi:nodetypes="sssss"/> </g> </g> <g inkscape:label="Boob_Small_Areolae_Wide" style="display:inline;opacity:1" id="Boob_Small_Areolae_Wide" inkscape:groupmode="layer"> - <g transformVariableName="_boob_right_art_transform" id="g2450"> + <g data-transform="boob_right" id="g2450"> <path sodipodi:nodetypes="caczsc" inkscape:connector-curvature="0" d="m 239.36986,227.39833 c 0,0 0.71277,8.23923 -0.67494,11.99618 -1.54558,4.18436 -8.11406,10.64147 -8.11406,10.64147 0,0 -3.24031,-8.7013 -2.48264,-11.5808 0.75767,-2.8795 0.64608,-3.04882 2.92925,-5.54348 2.87142,-3.13742 8.34239,-5.51337 8.34239,-5.51337 z" class="areola" id="path2448"/> </g> - <g transformVariableName="_boob_left_art_transform" id="g2454"> + <g data-transform="boob_left" id="g2454"> <path sodipodi:nodetypes="sssss" class="areola" d="m 315.07013,243.9018 c -6.9072,-0.76189 -13.8874,-5.85245 -13.92016,-10.41508 -0.0419,-5.82288 8.76879,-11.90016 16.50864,-11.56148 7.27826,0.31847 14.8736,5.06548 13.3816,12.12299 -1.49201,7.05753 -7.71129,10.76454 -15.97008,9.85357 z" id="path2452" inkscape:connector-curvature="0"/> </g> </g> <g inkscape:groupmode="layer" id="Boob_Small_Areolae_Huge" style="display:inline;opacity:1" inkscape:label="Boob_Small_Areolae_Huge"> - <g id="g2460" transformVariableName="_boob_right_art_transform"> + <g id="g2460" data-transform="boob_right"> <path id="path2458" class="areola" d="m 243.17821,224.74093 c 0,0 2.45622,9.86999 1.16254,14.56572 -1.70998,6.20677 -11.17982,15.74941 -11.17982,15.74941 0,0 -5.05432,-6.17604 -5.24261,-14.13117 -0.18828,-7.95513 0.0149,-2.81221 2.42761,-6.83709 3.03435,-5.06192 12.83228,-9.34687 12.83228,-9.34687 z" inkscape:connector-curvature="0" sodipodi:nodetypes="caczsc"/> </g> - <g id="g2464" transformVariableName="_boob_left_art_transform"> + <g id="g2464" data-transform="boob_left"> <path inkscape:connector-curvature="0" id="path2462" d="m 315.06318,249.00368 c -8.66357,-0.95563 -17.41869,-7.34062 -17.45978,-13.06343 -0.0525,-7.30353 10.99852,-14.92615 20.70646,-14.50135 9.12899,0.39946 18.65567,6.35353 16.78428,15.20563 -1.87139,8.85212 -9.67212,13.50176 -20.03096,12.35915 z" class="areola" sodipodi:nodetypes="sssss"/> </g> </g> <g inkscape:label="Boob_Small_Areolae_Star" style="display:inline;opacity:1" id="Boob_Small_Areolae_Star" inkscape:groupmode="layer"> - <g transformVariableName="_boob_right_art_transform" id="g2470"> + <g data-transform="boob_right" id="g2470"> <path sodipodi:nodetypes="cccccccssc" inkscape:connector-curvature="0" d="m 240.29933,227.09802 c -5.18428,3.30051 -7.99474,6.86395 -7.99474,6.86395 0,0 5.67867,-0.38365 11.0749,1.50681 -6.37633,0.70776 -10.4201,3.2349 -10.4201,3.2349 0,0 0.13997,6.94247 1.84947,12.07033 -2.42771,-2.29651 -5.33947,-9.68006 -5.33947,-9.68006 0,0 -0.3282,3.79742 1.03998,8.23505 -1.98466,-2.89505 -2.17172,-7.40591 -2.3519,-9.33994 -0.17874,-1.91868 0.16998,-2.80786 2.53329,-5.94212 3.16348,-4.19549 9.60857,-6.94892 9.60857,-6.94892 z" class="areola" id="path2468"/> </g> - <g transformVariableName="_boob_left_art_transform" id="g2474"> + <g data-transform="boob_left" id="g2474"> <path sodipodi:nodetypes="ccccccccccc" class="areola" d="m 314.46943,234.27224 c -3.76567,1.79157 -6.84161,5.28921 -10.10232,7.39152 1.44885,-3.26388 2.80438,-7.85021 4.89355,-10.83394 -2.31674,-1.93975 -5.18388,-2.96451 -8.37065,-3.68536 3.56307,-1.07962 7.79205,-1.81135 11.55083,-1.25273 1.41528,-1.99803 2.88366,-2.69755 5.19852,-4.40935 0.47133,1.75669 1.08677,2.27498 2.38302,4.27914 4.40924,-0.57094 8.75671,0.34013 13.32809,1.37553 -4.74363,0.78623 -8.39968,1.78672 -11.63843,3.96162 1.36056,2.93262 2.11025,7.4758 2.95271,10.6874 -2.99455,-2.42622 -6.28672,-5.87702 -10.19532,-7.51383 z" id="path2472" inkscape:connector-curvature="0"/> </g> </g> <g inkscape:label="Boob_Small_Areolae_Heart" style="display:inline;opacity:1" id="Boob_Small_Areolae_Heart" inkscape:groupmode="layer"> - <g transformVariableName="_boob_right_art_transform" id="g2480"> + <g data-transform="boob_right" id="g2480"> <path sodipodi:nodetypes="czcac" inkscape:connector-curvature="0" d="m 231.56989,252.42514 c -1.22195,-2.10852 -4.20293,-10.7371 -3.39892,-14.26628 0.80401,-3.52918 1.44795,-3.28007 4.67241,-5.19203 1.07003,-1.07003 5.21528,-2.42178 6.54597,-0.67782 4.36779,5.72431 -3.67752,10.857 -7.81946,20.13613 z" class="areola" id="path2478"/> </g> - <g transformVariableName="_boob_left_art_transform" id="g2484"> + <g data-transform="boob_left" id="g2484"> <path sodipodi:nodetypes="czczcc" class="areola" d="m 313.44442,246.20895 c -4.20528,-2.9951 -12.71977,-16.79856 -6.01226,-22.33579 6.70751,-5.53723 9.65531,-0.0103 9.65531,-0.0103 0,0 5.61579,-5.19127 10.77973,1.06406 5.16394,6.25533 -9.37618,18.97767 -14.42277,21.28185 z" id="path2482" inkscape:connector-curvature="0"/> </g> </g> <g inkscape:groupmode="layer" id="Boob_Small_Nipples" style="display:inline;opacity:1" inkscape:label="Boob_Small_Nipples"> - <g id="g2261" transformVariableName="_boob_right_art_transform"> + <g id="g2261" data-transform="boob_right"> <path id="path2251" class="shadow" d="m 228.15788,238.27703 c 0,0 -1.69507,-0.53274 -1.71244,-1.85211 0.0822,-1.64738 1.97278,-3.7797 3.37857,-3.08983 0.61419,0.34349 1.0323,0.99576 1.0323,0.99576 -0.0631,2.02891 -0.89639,3.0666 -2.69843,3.94618 z" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccc"/> <path sodipodi:nodetypes="ccccc" inkscape:connector-curvature="0" d="m 228.15788,238.27703 c 0,0 -1.71287,-0.63317 -1.71244,-1.85211 0.0582,-1.50008 2.07725,-3.77384 3.37857,-3.08983 0.53396,0.31477 1.0323,0.99576 1.0323,0.99576 -0.0695,1.89392 -0.94491,3.08122 -2.69843,3.94618 z" class="areola" id="path2253"/> <path id="path2255" class="shadow" d="m 226.82891,235.33246 c 0.4671,-0.43506 0.95746,-0.39751 2.03265,-0.2697 -0.95835,0.0287 -1.3927,-0.20327 -2.03265,0.2697 z" inkscape:connector-curvature="0" sodipodi:nodetypes="ccc"/> <path id="path2257" class="shadow" d="m 227.54865,235.02726 c -0.0294,-0.24033 0.0356,-0.69542 0.57576,-0.79154 -0.60268,0.23726 -0.50582,0.5033 -0.57576,0.79154 z" inkscape:connector-curvature="0" sodipodi:nodetypes="ccc"/> <path id="path2259" class="shadow" d="m 229.12691,238.41526 c 1.38286,-0.93932 2.12052,-2.43098 1.67838,-3.53558 0.24777,0.68434 0.5439,2.16936 -1.67838,3.53558 z" inkscape:connector-curvature="0" sodipodi:nodetypes="ccc"/> </g> - <g id="g2277" transformVariableName="_boob_left_art_transform"> + <g id="g2277" data-transform="boob_left"> <path inkscape:connector-curvature="0" id="path2265" d="m 313.17342,229.48817 c -0.54304,-0.69859 -0.45339,-1.79081 -0.30362,-2.30073 0.3611,-1.37094 1.95228,-2.06832 3.33841,-2.049 1.21548,0.0169 1.90412,0.19475 2.44948,1.27776 0.59205,0.46086 0.63124,1.24817 0.60041,1.28371 -0.16171,1.13935 -0.91614,2.77485 -3.12982,2.68352 -1.77607,0.0895 -2.38275,-0.0237 -2.95486,-0.89526 z" class="shadow" sodipodi:nodetypes="ccscccc"/> <path sodipodi:nodetypes="csscccc" class="areola" d="m 313.17342,229.48817 c -0.37088,-0.71581 -0.44918,-1.79919 -0.30362,-2.30073 0.38087,-1.31237 2.09965,-2.03413 3.33841,-2.049 1.22123,-0.0146 1.91113,0.36309 2.44948,1.27776 0.49616,0.54803 0.61883,1.25946 0.60041,1.28371 -0.2124,1.06614 -0.96439,2.70517 -3.12982,2.68352 -1.67427,0.002 -2.33494,-0.0646 -2.95486,-0.89526 z" id="path2267" inkscape:connector-curvature="0"/> <path inkscape:connector-curvature="0" id="path2269" d="m 313.95456,226.60231 c 1.19002,-0.4627 2.32428,0.16299 3.06225,0.78272 -0.88614,-0.43236 -2.01938,-1.0249 -3.06225,-0.78272 z" class="shadow" sodipodi:nodetypes="ccc"/> @@ -2028,13 +2028,13 @@ </g> <g inkscape:groupmode="layer" id="Boob_Small_Piercings_" inkscape:label="Boob_Small_Piercings_" style="display:inline"> <g inkscape:groupmode="layer" id="Boob_Small_Areola_Piercing" style="display:inline" inkscape:label="Boob_Small_Areola_Piercing"> - <g id="g2489" transformVariableName="_boob_left_art_transform"> + <g id="g2489" data-transform="boob_left"> <path class="shadow" sodipodi:nodetypes="accaa" id="path5169" d="m 320.43194,225.09759 c -5e-5,0.717 -0.77245,1.51654 -1.52538,1.51654 -0.5209,-0.31622 -0.64486,-0.92927 -1.6847,-1.41308 0,-0.74876 0.8338,-1.68143 1.61288,-1.69181 0.75078,-0.0101 1.59725,0.83751 1.5972,1.58835 z" inkscape:connector-curvature="0"/> <path class="shadow" sodipodi:nodetypes="aaaaa" id="path5171" d="m 315.94907,234.83564 c 0,0.75084 -0.84635,1.58836 -1.5972,1.58836 -0.75085,0 -1.5972,-0.83752 -1.5972,-1.58836 0,-0.75085 0.84635,-1.58835 1.5972,-1.58835 0.75085,0 1.5972,0.8375 1.5972,1.58835 z" inkscape:connector-curvature="0"/> <path inkscape:connector-curvature="0" d="m 320.28791,225.09759 c 0,0.68259 -0.76752,1.44396 -1.452,1.44396 -0.47354,-0.28747 -0.59653,-0.82419 -1.54184,-1.26402 0,-0.68069 0.79549,-1.61319 1.54184,-1.6239 0.68252,-0.01 1.452,0.76138 1.452,1.44396 z" id="path2749-8-39" sodipodi:nodetypes="accaa" class="steel_piercing"/> <path inkscape:connector-curvature="0" d="m 315.80387,234.83564 c 0,0.68259 -0.76941,1.44396 -1.452,1.44396 -0.68259,0 -1.452,-0.76137 -1.452,-1.44396 0,-0.68259 0.76941,-1.44396 1.452,-1.44396 0.68259,0 1.452,0.76137 1.452,1.44396 z" id="path2749-8-42" sodipodi:nodetypes="aaaaa" class="steel_piercing"/> </g> - <g id="g2495" transformVariableName="_boob_right_art_transform"> + <g id="g2495" data-transform="boob_right"> <path class="shadow" sodipodi:nodetypes="aaaaa" id="path5173" d="m 236.01142,231.24698 c 0,0.75084 -0.84635,1.58835 -1.5972,1.58835 -0.75085,0 -1.5972,-0.83751 -1.5972,-1.58835 0,-0.75085 0.84635,-1.58836 1.5972,-1.58836 0.75085,0 1.5972,0.83751 1.5972,1.58836 z" inkscape:connector-curvature="0"/> <path class="shadow" sodipodi:nodetypes="aaaaa" id="path5175" d="m 229.91767,242.70346 c 0,0.75085 -0.84635,1.58835 -1.5972,1.58835 -0.75085,0 -1.5972,-0.8375 -1.5972,-1.58835 0,-0.75084 0.84635,-1.58836 1.5972,-1.58836 0.75085,0 1.5972,0.83752 1.5972,1.58836 z" inkscape:connector-curvature="0"/> <path inkscape:connector-curvature="0" d="m 235.86622,231.24698 c 0,0.68258 -0.76941,1.44396 -1.452,1.44396 -0.68259,0 -1.452,-0.76138 -1.452,-1.44396 0,-0.68259 0.76941,-1.44396 1.452,-1.44396 0.68259,0 1.452,0.76137 1.452,1.44396 z" id="path2749-8-40" sodipodi:nodetypes="aaaaa" class="steel_piercing"/> @@ -2042,19 +2042,19 @@ </g> </g> <g inkscape:label="Boob_Small_Areola_Piercing_Heavy" style="display:inline" id="Boob_Small_Areola_Piercing_Heavy" inkscape:groupmode="layer"> - <g id="g2471" transformVariableName="_boob_left_art_transform"> + <g id="g2471" data-transform="boob_left"> <path inkscape:connector-curvature="0" d="m 321.68714,227.27176 c 0,0 -0.13465,-4.47036 1.43,-5.58749 1.85611,-1.32523 5.3301,-1.17893 6.82,0.54779 1.43465,1.66269 0.96516,4.88585 -0.44,6.57352 -1.13778,1.36653 -5.17,1.3147 -5.17,1.3147 0,0 3.53534,-0.86422 4.29,-2.30073 0.61522,-1.17109 0.47784,-2.99147 -0.44,-3.94411 -1.02892,-1.06792 -3.08003,-1.33322 -4.4,-0.65735 -1.35317,0.69288 -2.09,4.05367 -2.09,4.05367 z" class="shadow" id="path5163" sodipodi:nodetypes="caaacaaac"/> <path inkscape:connector-curvature="0" d="m 311.95601,227.50867 c 0,0 0.13465,-4.47036 -1.43,-5.58748 -1.85611,-1.32524 -5.3301,-1.17894 -6.82,0.54779 -1.43465,1.66269 -0.96517,4.88583 0.44,6.57352 1.13778,1.36652 5.17,1.3147 5.17,1.3147 0,0 -3.53534,-0.86423 -4.29,-2.30073 -0.61522,-1.17109 -0.47784,-2.99147 0.44,-3.94411 1.02891,-1.06792 3.08003,-1.33322 4.4,-0.65735 1.35317,0.69286 2.09,4.05366 2.09,4.05366 z" class="shadow" id="path5165" sodipodi:nodetypes="caaacaaac"/> <path sodipodi:nodetypes="caaacaaac" id="XMLID_525_-3-4" class="steel_piercing" d="m 322.10179,227.10721 c 0,0 -0.12241,-4.06396 1.3,-5.07953 1.68737,-1.20475 4.84554,-1.07176 6.2,0.49799 1.30422,1.51154 0.87742,4.44168 -0.4,5.97592 -1.03434,1.2423 -4.7,1.19519 -4.7,1.19519 0,0 3.21395,-0.78566 3.9,-2.09157 0.55929,-1.06462 0.4344,-2.71952 -0.4,-3.58556 -0.93538,-0.97084 -2.80003,-1.21202 -4,-0.59759 -1.23016,0.62989 -1.9,3.68515 -1.9,3.68515 z" inkscape:connector-curvature="0"/> <path sodipodi:nodetypes="caaacaaac" id="XMLID_525_-3-4-7" class="steel_piercing" d="m 311.54136,227.34413 c 0,0 0.12241,-4.06397 -1.3,-5.07954 -1.68737,-1.20475 -4.84554,-1.07175 -6.2,0.498 -1.30422,1.51154 -0.87742,4.44167 0.4,5.97592 1.03434,1.2423 4.7,1.19519 4.7,1.19519 0,0 -3.21395,-0.78567 -3.9,-2.09158 -0.5593,-1.06463 -0.4344,-2.71951 0.4,-3.58555 0.93538,-0.97084 2.80003,-1.21202 4,-0.5976 1.23016,0.62989 1.9,3.68516 1.9,3.68516 z" inkscape:connector-curvature="0"/> </g> - <g id="g2475" transformVariableName="_boob_right_art_transform"> + <g id="g2475" data-transform="boob_right"> <path inkscape:connector-curvature="0" d="m 232.11707,235.48695 c 0,0 0.60967,-2.2986 1.54375,-2.82951 2.13513,-1.21356 5.78847,-1.60777 7.36253,0.2774 0.71838,0.86038 0.32663,2.54546 -0.475,3.32885 -1.34,1.30952 -5.58127,0.66577 -5.58127,0.66577 0,0 3.80544,0.19579 4.63127,-1.1651 0.35502,-0.58505 0.0468,-1.55454 -0.47501,-1.99731 -1.21025,-1.02692 -3.25057,-0.85339 -4.75002,-0.33288 -0.96055,0.33345 -2.25625,2.05278 -2.25625,2.05278 z" class="shadow" id="path5167" sodipodi:nodetypes="caaacaaac"/> <path sodipodi:nodetypes="caaacaaac" id="XMLID_525_-3-4-3" class="steel_piercing" d="m 232.53913,235.38469 c 0,0 0.55425,-2.08965 1.40341,-2.57229 1.94103,-1.10324 5.26225,-1.46161 6.69321,0.25218 0.65308,0.78216 0.29694,2.31406 -0.43182,3.02623 -1.21818,1.19046 -5.07388,0.60524 -5.07388,0.60524 0,0 3.45949,0.17799 4.21024,-1.05918 0.32275,-0.53186 0.0425,-1.41322 -0.43182,-1.81574 -1.10022,-0.93356 -2.95507,-0.77581 -4.3182,-0.30262 -0.87323,0.30314 -2.05114,1.86618 -2.05114,1.86618 z" inkscape:connector-curvature="0"/> </g> </g> <g inkscape:groupmode="layer" id="Boob_Small_Piercing_Heavy" style="display:inline" inkscape:label="Boob_Small_Piercing_Heavy"> - <g id="g3131" transformVariableName="_boob_left_art_transform"> + <g id="g3131" data-transform="boob_left"> <path inkscape:connector-curvature="0" d="m 310.74124,223.29137 c 0,0 -2.49411,9.18373 -0.98325,13.39981 1.04424,2.91398 3.31774,6.91285 6.40728,6.7218 3.05706,-0.18905 4.59483,-4.44702 5.47216,-7.38158 1.2346,-4.12965 -0.7356,-12.9098 -0.7356,-12.9098 0,0 0.11352,1.8255 0.16679,3.66985 -0.16929,0.006 -2.35051,-4.1e-4 -2.35051,-4.1e-4 0.0559,0.37078 -0.0172,0.52908 -0.0182,0.90408 0,0 2.10319,-0.01 2.38726,-0.0165 0.0394,2.95347 -0.12672,6.29356 -1.09131,8.44744 -0.78349,1.74932 -2.10939,3.66042 -3.89433,3.67566 -1.987,0.017 -3.50956,-2.07688 -4.40441,-4.01713 -0.94479,-2.04857 -1.13062,-5.2179 -1.1115,-8.05448 0.44876,0 2.16836,-0.0536 2.16836,-0.0536 l 0.0221,-0.91124 c 0,0 -1.72384,-0.0132 -2.17613,-0.0132 0.0399,-1.72733 0.14124,-3.46134 0.14124,-3.46134 z" class="shadow" id="path5090" sodipodi:nodetypes="caaacccccsascccccc"/> <path inkscape:connector-curvature="0" d="m 316.17757,240.04058 c 0,0 -1.85221,9.4952 -1.92044,14.30624 -0.078,5.49738 1.72993,16.40283 1.72993,16.40283 0,0 -0.37012,-9.79442 1.09665,-19.6094 -0.97824,-3.25724 -0.90614,-11.09967 -0.90614,-11.09967 z" class="shadow" id="path5094" sodipodi:nodetypes="caccc"/> <path inkscape:connector-curvature="0" d="m 315.92337,268.73978 c 0,0 -1.08608,3.59047 -0.98853,5.42648 0.0928,1.74745 1.48279,5.03598 1.48279,5.03598 0,0 1.05088,-3.32642 0.98853,-5.03598 -0.0684,-1.8739 -1.48279,-5.42648 -1.48279,-5.42648 z" class="shadow" id="path5096" sodipodi:nodetypes="cacac"/> @@ -2062,7 +2062,7 @@ <path sodipodi:nodetypes="caccc" id="XMLID_513_-8-0-8" class="steel_piercing" d="m 316.13135,241.43645 c 0,0 -1.68382,8.632 -1.74585,13.00567 -0.0709,4.99762 1.57266,14.91166 1.57266,14.91166 0,0 -0.33647,-8.90402 0.99696,-17.82673 -0.88931,-2.96113 -0.82377,-10.0906 -0.82377,-10.0906 z" inkscape:connector-curvature="0"/> <path sodipodi:nodetypes="cacac" id="XMLID_514_-2-7-8" class="steel_piercing" d="m 315.94568,269.21534 c 0,0 -0.98735,3.26408 -0.89867,4.93318 0.0844,1.58858 1.34799,4.57815 1.34799,4.57815 0,0 0.95535,-3.02401 0.89867,-4.57815 -0.0621,-1.70355 -1.34799,-4.93318 -1.34799,-4.93318 z" inkscape:connector-curvature="0"/> </g> - <g id="g3139" transformVariableName="_boob_right_art_transform"> + <g id="g3139" data-transform="boob_right"> <path inkscape:connector-curvature="0" d="m 232.41948,231.80744 c 0,0 1.84875,9.08379 0.67687,13.39983 -0.70222,2.58629 -1.73488,6.86756 -4.41084,6.72179 -2.75834,-0.15026 -3.17412,-4.68357 -3.76709,-7.3816 -0.92442,-4.20618 0.5064,-12.90978 0.5064,-12.90978 0,0 -0.0782,1.73915 -0.11483,3.58349 0.11654,0.006 1.459,-4.1e-4 1.459,-4.1e-4 l -0.43147,0.90407 c 0,0 -0.84471,-0.01 -1.04027,-0.0165 -0.0271,2.95346 0.0873,6.37993 0.75126,8.5338 0.53937,1.74933 1.16447,3.66321 2.68091,3.67564 1.67758,0.0138 2.41602,-2.07685 3.03204,-4.01709 0.65041,-2.04858 0.77834,-5.30427 0.76517,-8.14084 -0.30893,0 -1.87642,-0.0536 -1.87642,-0.0536 0.0596,-0.36182 0.0683,-0.46339 0.2179,-0.91125 0,0 1.33728,-0.0132 1.64865,-0.0132 -0.0275,-1.72732 -0.0972,-3.37499 -0.0972,-3.37499 z" class="shadow" id="path5092" sodipodi:nodetypes="caaacccccsascccccc"/> <path inkscape:connector-curvature="0" d="m 229.06632,249.43465 c 0,0 -1.8522,9.4952 -1.92044,14.30623 -0.078,5.49738 1.72993,16.40284 1.72993,16.40284 0,0 -0.37012,-9.79444 1.09665,-19.6094 -0.97824,-3.25724 -0.90614,-11.09967 -0.90614,-11.09967 z" class="shadow" id="path5098" sodipodi:nodetypes="caccc"/> <path inkscape:connector-curvature="0" d="m 228.81212,278.13384 c 0,0 -1.08607,3.59049 -0.98853,5.4265 0.0928,1.74744 1.48279,5.03595 1.48279,5.03595 0,0 1.05088,-3.3264 0.98853,-5.03595 -0.0683,-1.8739 -1.48279,-5.4265 -1.48279,-5.4265 z" class="shadow" id="path5100" sodipodi:nodetypes="cacac"/> @@ -2073,13 +2073,13 @@ </g> <g inkscape:label="Boob_Small_Piercing" style="display:inline" id="Boob_Small_Piercing" inkscape:groupmode="layer"> <g id="g1366" style="fill:#c0c6c7;fill-opacity:1;stroke:none;stroke-opacity:1"/> - <g id="g4019" style="fill:#c0c6c7;fill-opacity:1;stroke:none;stroke-opacity:1" transformVariableName="_boob_left_art_transform"> + <g id="g4019" style="fill:#c0c6c7;fill-opacity:1;stroke:none;stroke-opacity:1" data-transform="boob_left"> <path class="shadow" sodipodi:nodetypes="aaaaa" id="path5080" d="m 321.89408,227.57109 c 0,0.74947 -0.84077,1.5972 -1.5972,1.5972 -0.75643,0 -1.5972,-0.84773 -1.5972,-1.5972 0,-0.74947 0.84077,-1.5972 1.5972,-1.5972 0.75643,0 1.5972,0.84773 1.5972,1.5972 z" inkscape:connector-curvature="0"/> <path class="shadow" sodipodi:nodetypes="saccs" id="path5082" d="m 313.02276,229.35579 c -0.75293,0 -1.63873,-0.84886 -1.5972,-1.5972 0.0463,-0.83367 1.21255,-1.57531 1.96548,-1.57531 -0.68775,1.21129 -0.7805,1.82947 -0.3682,3.17251 z" inkscape:connector-curvature="0"/> <path inkscape:connector-curvature="0" d="m 321.74888,227.57109 c 0,0.68134 -0.76433,1.452 -1.452,1.452 -0.68767,0 -1.452,-0.77066 -1.452,-1.452 0,-0.68134 0.76433,-1.452 1.452,-1.452 0.68767,0 1.452,0.77066 1.452,1.452 z" id="path2749-8-1" sodipodi:nodetypes="aaaaa" class="steel_piercing"/> <path inkscape:connector-curvature="0" d="m 313.02164,229.21059 c -0.68448,0 -1.48776,-0.77159 -1.452,-1.452 0.0401,-0.76308 1.10584,-1.452 1.79032,-1.452 -0.71906,1.10285 -0.73484,1.67672 -0.33828,2.904 z" id="path2749-8-37" sodipodi:nodetypes="saccs" class="steel_piercing"/> </g> - <g style="display:inline" id="g3034" transformVariableName="_boob_right_art_transform"> + <g style="display:inline" id="g3034" data-transform="boob_right"> <path inkscape:connector-curvature="0" d="m 231.70657,235.61491 c 0,0.74947 -0.84076,1.5972 -1.5972,1.5972 -0.75643,0 -1.5972,-0.84773 -1.5972,-1.5972 0,-0.74947 0.84077,-1.5972 1.5972,-1.5972 0.75644,0 1.5972,0.84773 1.5972,1.5972 z" id="path5084" sodipodi:nodetypes="aaaaa" class="shadow" transform="matrix(1,0,0,1.0092899,0,-2.0984812)"/> <path inkscape:connector-curvature="0" d="m 226.57248,236.96752 c -0.34466,-0.31248 -0.76627,-0.64473 -0.76627,-1.05102 0,-0.75293 0.84427,-1.5972 1.5972,-1.5972 -0.78404,0.89358 -0.91059,1.20611 -0.83093,2.64822 z" id="path5086" sodipodi:nodetypes="cscc" class="shadow" transform="matrix(1,0,0,1.0092899,0,-2.0984812)"/> <path class="steel_piercing" sodipodi:nodetypes="aaaaa" id="path2749-8-1-1" d="m 231.56137,235.61491 c 0,0.68134 -0.76433,1.452 -1.452,1.452 -0.68766,0 -1.452,-0.77066 -1.452,-1.452 0,-0.68133 0.76434,-1.452 1.452,-1.452 0.68767,0 1.452,0.77067 1.452,1.452 z" inkscape:connector-curvature="0" transform="matrix(1,0,0,1.0092899,0,-2.0984812)"/> @@ -2089,7 +2089,7 @@ </g> <g inkscape:label="Boob_Small_Highlights" id="Boob_Small_Highlights" inkscape:groupmode="layer" style="display:inline"> <g style="display:inline" inkscape:label="Boob_Small_Highlights2" id="Boob_Small_Highlights2" inkscape:groupmode="layer"> - <g transformVariableName="_boob_left_art_transform" id="g2519"> + <g data-transform="boob_left" id="g2519"> <path inkscape:connector-curvature="0" d="m 321.85975,215.92692 c -1.89715,1.20251 -6.31642,3.88396 -3.175,7.57381 4.21646,-0.071 4.26738,-5.70386 3.175,-7.57381 z" class="highlight2" id="path2507" sodipodi:nodetypes="ccc"/> <path inkscape:connector-curvature="0" d="m 314.90689,235.99789 c -3.52683,3.26178 -5.76341,8.34571 -1.88762,10.3195 2.98911,-1.10062 3.7767,-5.82866 1.88762,-10.3195 z" class="highlight2" id="path2509" sodipodi:nodetypes="ccc"/> <path inkscape:connector-curvature="0" d="m 315.18349,232.60131 c -1.45195,1.21811 -0.55284,1.57513 -0.29636,2.05122 0.91423,-0.4922 1.12461,-0.75849 0.29636,-2.05122 z" class="highlight2" id="path2511" sodipodi:nodetypes="ccc"/> @@ -2097,7 +2097,7 @@ <path inkscape:connector-curvature="0" d="m 316.82316,228.06367 c -1.11294,-1.53405 -2.19421,-0.93805 -2.68716,-0.71571 0.55046,0.56081 1.587,0.71901 2.68716,0.71571 z" class="highlight2" id="path2515" sodipodi:nodetypes="ccc"/> <path inkscape:connector-curvature="0" d="m 316.69673,225.30909 c -1.29574,-0.23601 -1.88877,0.15883 -2.19442,0.60489 1.134,0.2189 1.34152,0.27164 2.19442,-0.60489 z" class="highlight2" id="path2517" sodipodi:nodetypes="ccc"/> </g> - <g transformVariableName="_boob_right_art_transform" id="g2560"> + <g data-transform="boob_right" id="g2560"> <path inkscape:connector-curvature="0" d="m 259.03954,222.95658 c -7.62159,-1.9871 -15.09403,5.90489 -17.77314,7.66238 4.07679,1.14519 17.22608,2.90775 17.77314,-7.66238 z" class="highlight2" id="path2522" sodipodi:nodetypes="ccc"/> <path inkscape:connector-curvature="0" d="m 265.10282,214.91201 c -0.95282,-0.17319 -2.05051,0.57552 -1.97909,1.35787 0.65101,0.10861 1.99182,0.29621 1.97909,-1.35787 z" class="highlight2" id="path2526" sodipodi:nodetypes="ccc"/> <path inkscape:connector-curvature="0" d="m 240.11624,228.02619 c -0.88548,-0.39214 -2.12833,0.0778 -2.24268,0.85503 0.6073,0.25848 1.86652,0.75577 2.24268,-0.85503 z" class="highlight2" id="path2531" sodipodi:nodetypes="ccc"/> @@ -2109,11 +2109,11 @@ </g> </g> <g inkscape:groupmode="layer" id="Boob_Small_Highlights1" inkscape:label="Boob_Small_Highlights1" style="display:inline"> - <g transformVariableName="_boob_left_art_transform" transform="matrix(1.0060951,0,0,1.0060951,-1.9605124,-1.2116124)" id="g2569"> + <g data-transform="boob_left" transform="matrix(1.0060951,0,0,1.0060951,-1.9605124,-1.2116124)" id="g2569"> <path sodipodi:nodetypes="ccc" id="path2564" class="highlight1" d="m 320.21266,218.71568 c -1.90013,1.2044 -1.89258,3.23381 -1.52692,4.67945 1.21541,-0.6336 2.621,-2.80656 1.52692,-4.67945 z" inkscape:connector-curvature="0"/> <path sodipodi:nodetypes="ccc" id="path2567" class="highlight1" d="m 314.8764,235.91371 c -1.68861,1.7669 -1.74121,4.42131 -1.45308,5.80445 1.40005,-1.16485 2.00138,-3.93156 1.45308,-5.80445 z" inkscape:connector-curvature="0"/> </g> - <g transformVariableName="_boob_right_art_transform" id="g2573"> + <g data-transform="boob_right" id="g2573"> <path sodipodi:nodetypes="ccc" id="path2571" class="highlight1" d="m 252.94473,226.59339 c -4.7273,0.75979 -7.83647,2.53916 -10.64479,3.98691 4.08319,1.14699 9.56562,1.06857 10.64479,-3.98691 z" inkscape:connector-curvature="0" transform="matrix(1.0060951,0,0,1.0060951,-1.9605124,-1.2116124)"/> </g> </g> @@ -2263,14 +2263,14 @@ </g> </g> <g inkscape:groupmode="layer" id="Boob_Small_Outfit_Maid" inkscape:label="Boob_Small_Outfit_Maid" style="display:inline;opacity:1"> - <g style="display:inline;opacity:1" id="g2134" transformVariableName="_boob_outfit_art_transform"> + <g style="display:inline;opacity:1" id="g2134" data-transform="boob_outfit"> <path transform="matrix(1.0048669,0,0,1.0048669,-1.648066,-0.97431337)" style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke-width:0.99515665" d="m 239.54885,237.04157 c -4.04819,7.94613 1.44538,18.58593 8.83122,22.81636 8.09471,6.43684 19.83019,-1.39546 30.03417,-2.40951 14.56784,0.39988 33.00884,8.74574 45.2163,-1.3044 10.61336,-7.56078 12.07589,-24.40116 5.67382,-34.87417 -7.36879,-13.11973 -24.34612,-5.89309 -39.2914,-4.14233 -19.08654,2.23589 -45.57307,0.78903 -50.46411,19.91405 z" id="path2802" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccccc"/> <path sodipodi:nodetypes="aaaaaaa" inkscape:connector-curvature="0" id="path2130" d="m 239.54885,237.04157 c -2.74035,7.68108 1.92475,18.4794 8.83122,22.81636 8.5056,5.34113 20.0055,-1.86294 30.03417,-2.40951 15.05602,-0.82057 33.63673,8.35329 45.2163,-1.3044 9.12655,-7.61181 13.40486,-24.61335 7.40909,-34.87417 -7.23069,-12.3742 -26.77543,-14.38112 -41.02667,-12.86259 -19.23179,2.04922 -43.96524,10.41822 -50.46411,28.63431 z" style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke-width:0.99515665" transform="matrix(1.0048669,0,0,1.0048669,-1.648066,-0.97431337)"/> </g> </g> <g style="display:inline;opacity:1" inkscape:label="Boob_Medium_Outfit_Maid" id="Boob_Medium_Outfit_Maid" inkscape:groupmode="layer"> <g id="g2809" style="display:inline;opacity:1" clip-path="url(#clipPath2523)"> - <g id="g2538" transformVariableName="_boob_outfit_art_transform"> + <g id="g2538" data-transform="boob_outfit"> <path style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke-width:0.99515665" d="m 227.00685,243.38843 c -2.76471,9.20616 1.1523,22.46284 10.23433,26.44142 13.66316,10.50116 31.65638,-1.69767 47.38431,-2.79233 21.61943,-0.77747 47.79009,14.35634 64.89544,-1.51164 12.83936,-8.09143 12.84724,-26.23313 11.44045,-40.41498 0.7133,-22.58264 -24.44265,-62.6023 -24.52354,-62.59331 -0.004,-0.002 -98.3921,36.39445 -109.43099,80.87084 z" id="path2459" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccccc"/> <path sodipodi:nodetypes="aaaaaca" inkscape:connector-curvature="0" id="path2806" d="m 227.00685,243.38843 c -2.63483,9.07628 2.28426,21.33088 10.23433,26.44142 13.30944,8.5557 31.57548,-2.14261 47.38431,-2.79233 21.61943,-0.88852 47.79009,11.73964 64.89544,-1.51164 11.06829,-8.57445 12.1231,-26.43062 11.44045,-40.41498 -1.09258,-22.38199 -24.52354,-62.59331 -24.52354,-62.59331 0,0 -96.78599,37.31223 -109.43099,80.87084 z" style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke-width:0.99515665"/> </g> @@ -2278,7 +2278,7 @@ </g> <g inkscape:groupmode="layer" id="Boob_Huge_Outfit_Maid" inkscape:label="Boob_Huge_Outfit_Maid" style="display:inline;opacity:1"> <g id="g2511" clip-path="url(#clipPath2523)"> - <g id="g2501" transformVariableName="_boob_outfit_art_transform"> + <g id="g2501" data-transform="boob_outfit"> <path sodipodi:nodetypes="cccccccc" inkscape:connector-curvature="0" id="path2481" d="m 248.46348,221.30205 c -7.84799,13.39188 -9.31561,33.03051 1.17873,45.75168 8.18024,12.33371 22.62994,9.84279 34.81926,7.11239 10.16499,1.36382 18.37185,1.37376 32.10564,1.83999 11.54119,4.46467 21.63893,4.78374 30.06923,-2.42885 13.78259,-9.95091 14.54789,-23.07261 13.81906,-47.30239 1.67109,-21.37616 -23.40629,-68.10261 -23.40629,-68.10261 0,0 -76.87136,32.99996 -88.58563,63.12979 z" style="display:inline;opacity:1;fill:#1a1a1a;fill-opacity:1;stroke-width:0.99515665"/> <path style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke-width:0.99515665" d="m 248.46348,221.30205 c -6.81285,13.64987 -7.73759,33.34658 1.17873,45.75168 8.43153,11.73061 22.90015,9.19429 34.81926,7.11239 10.50108,1.06974 18.86406,0.94308 32.10564,1.83999 12.09113,3.70602 22.27287,3.92208 30.06923,-2.42885 12.73576,-10.37458 14.2035,-30.88034 13.81906,-47.30239 -0.56178,-23.99764 -23.40629,-68.10261 -23.40629,-68.10261 0,0 -72.39285,30.6868 -88.58563,63.12979 z" id="path2826" inkscape:connector-curvature="0" sodipodi:nodetypes="asccaaca"/> <path inkscape:connector-curvature="0" d="m 311.72503,274.95345 c -18.32365,-4.27958 -40.32075,-0.75207 -49.31724,-0.21926 9.0114,-0.53368 36.99108,-2.65958 49.31724,0.21926 z" class="shadow" id="path3232-3-3" sodipodi:nodetypes="ccc"/> diff --git a/compile.sh b/compile.sh index ebc27c41a500f9d9b6f4fbadfb0160b9175449b3..ca18ce3d5cb1a0dae61f6e61ddaa9ad6b813d767 100755 --- a/compile.sh +++ b/compile.sh @@ -137,4 +137,4 @@ if [[ "$dry" ]]; then else compile echoMessage "Compilation finished." -fi \ No newline at end of file +fi diff --git a/devTools/sugarcube.d.ts b/devTools/sugarcube.d.ts index 1239e18b202abb406ce70b66c0a7b258a28b4f3a..d989bf9da5a7b35d2da4cb183a6462bf3bbd14e5 100644 --- a/devTools/sugarcube.d.ts +++ b/devTools/sugarcube.d.ts @@ -1346,6 +1346,7 @@ declare global { */ const settings: SugarCubeLib.Settings; const Config: SugarCubeLib.Config; + const Engine: SugarCubeLib.Engine; const Macro: SugarCubeLib.Macro; let State: SugarCubeLib.State; let Story: SugarCubeLib.Story; @@ -1718,7 +1719,7 @@ declare global { * //Do something * } */ - function variables(): object; + function variables(): any; /** * Returns the number of times that the passage with the given title occurred within the story history. If multiple passage diff --git a/src/002-config/fc-js-init.js b/src/002-config/fc-js-init.js index f72c839f781d59d8ab0bd4132a07806d460af06b..7293afed2c1ac9780c936521a973c22cc5bab968 100644 --- a/src/002-config/fc-js-init.js +++ b/src/002-config/fc-js-init.js @@ -9,11 +9,13 @@ window.App = { }; // the same declaration for code parsers that don't like the line above var App = window.App || {}; /* eslint-disable-line no-var*/ +App.Art = {}; App.Data = {}; App.Debug = {}; App.Entity = {}; App.Entity.Utils = {}; App.UI = {}; +App.UI.DOM = {}; App.UI.View = {}; App.Utils = {}; App.Interact = {}; @@ -36,3 +38,9 @@ App.Facilities = { App.Medicine = {}; App.RA = {}; App.SF = {}; + + +Object.defineProperty(App, "activeSlave", { + get: () => State.variables.activeSlave, + set: (slave) => { State.variables.activeSlave = slave; } +}); diff --git a/src/003-assets/CSS/slaveList.css b/src/003-assets/CSS/slaveList.css new file mode 100644 index 0000000000000000000000000000000000000000..c0750f9317c2a1b8e535123baa1716d621df1786 --- /dev/null +++ b/src/003-assets/CSS/slaveList.css @@ -0,0 +1,35 @@ +div.slaveSummary { + clear: both; +} + +/* slave summary paragraph when "see images" is enabled */ +p.si { + margin-bottom: 0; + margin-top: 0; + text-indent: 1.5em; +} + +span.freeAssignment { + color: lawngreen; + text-decoration: underline; + font-weight: bold; +} + +/* Slave Summary Item */ +.ssi { + margin-right: 0.25em; +} + +/* Slave Summary Block */ +.ssb { + margin-right: 2em; +} + +.strong { + font-weight: bold; +} + +.emphasizedSlave{ + font-weight: bold; + text-decoration: underline; +} diff --git a/src/004-base/facility.js b/src/004-base/facility.js index 450d54fffa950ce81d85e83b5064d553d89726d7..1298e01d2001f7ef8cc026f1952a01b00120c284 100644 --- a/src/004-base/facility.js +++ b/src/004-base/facility.js @@ -104,6 +104,12 @@ App.Entity.Facilities.Job = class { * @returns {string} code to include into the <<link>><</link>> */ + /** + * @callback assignmentCallback + * @param {string} assignment new assignment + * @returns {void} + */ + /** * Returns link text for the penthouse assignment * @param {number} i slave index @@ -118,6 +124,19 @@ App.Entity.Facilities.Job = class { return `<<link "${linkText}"${passage !== undefined ? ' "' + passage + '"' : ''}>><<= assignJob(${App.Utils.slaveRefString(i)}, "${this.desc.assignment}")>>${linkAction}<</link>>`; } + /** + * Returns link text for the penthouse assignment + * @param {number} i slave index + * @param {string} [passage] passage to go to + * @param {assignmentCallback} [callback] + * @param {string} [linkText] + * @returns {HTMLAnchorElement} + */ + assignmentLinkElement(i, passage, callback, linkText) { + linkText = linkText || this.desc.position; + return App.UI.DOM.assignmentLink(State.variables.slaves[i], this.desc.assignment, passage, callback, linkText); + } + /** * all slaves that are employed at this job * @returns {App.Entity.SlaveState[]} @@ -391,6 +410,32 @@ App.Entity.Facilities.Facility = class { return res; } + /** + * Returns link text for the job assignments + * @param {number} i slave index + * @param {string} [job] generate link only for this job + * @param {string} [passage] + * @param {assignmentCallback} callback + * @returns {HTMLElement[]} + */ + assignmentLinkElements(i, job, passage, callback) { + /** @type {App.Entity.SlaveState} */ + const slave = App.Utils.slaveByIndex(i); + const jobs = job === undefined ? this._jobs : {job: this._jobs[job]}; + + let res = []; + for (const jn in jobs) { + const j = jobs[jn]; + let rejects = j.canEmploy(slave); + if (rejects.length === 0) { + res.push(j.assignmentLinkElement(i, passage, callback)); + } else { + res.push(App.UI.DOM.disabledLink(j.desc.position, rejects)); + } + } + return res; + } + /** * Returns link text for the facility transfer * @param {number} i slave index @@ -404,6 +449,19 @@ App.Entity.Facilities.Facility = class { return this._jobs[job].assignmentLink(i, passage, callback, this.genericName); } + /** + * Returns link text for the facility transfer + * @param {number} i slave index + * @param {string} [job] transfer to this job (uses default job if this is undefined) + * @param {string} [passage] + * @param {linkCallback} [callback] + * @returns {HTMLElement} + */ + transferLinkElement(i, job, passage, callback) { + job = job || this.desc.defaultJob; + return this._jobs[job].assignmentLinkElement(i, passage, callback, this.genericName); + } + /** * all slaves that are employed at this job * @returns {App.Entity.SlaveState[]} diff --git a/src/Mods/DinnerParty/dinnerPartyPreparations.tw b/src/Mods/DinnerParty/dinnerPartyPreparations.tw index 4ae279d4fbcac7cb993bf4533599fb7934edf310..35000125b472aca6e9a630e0e52af4b2f878de55 100644 --- a/src/Mods/DinnerParty/dinnerPartyPreparations.tw +++ b/src/Mods/DinnerParty/dinnerPartyPreparations.tw @@ -35,6 +35,7 @@ __Select Your Meat:__ null, (s, i) => { const p = getPronouns(s); - return App.UI.passageLink(`Make ${p.him} the main course`, "Dinner Party Execution", `$activeSlave = $slaves[${i}]`) + return App.UI.DOM.passageLink(`Make ${p.him} the main course`, "Dinner Party Execution", + () => { App.Utils.setActiveSlaveByIndex(i); }) } )>> diff --git a/src/art/artJS.js b/src/art/artJS.js index fbe02537297fbef4ca7ecedd771cfaeb829f4340..d21cb483ecd31631a5e827b96c79f77f37f75431 100644 --- a/src/art/artJS.js +++ b/src/art/artJS.js @@ -26,9 +26,52 @@ window.SlaveArt = function(artSlave, artSize, UIDisplay) { } }; +/** + * @param {App.Entity.SlaveState} artSlave Slave + * @param {number} artSize Image size/center: + * * 3: Large, right. Example: long slave description. + * * 2: Medium, right. Example: random events. + * * 1: Small, left. Example: lists. + * * 0: Tiny, left. Example: facilities + * @param {number} [UIDisplay] (optional, only used by legacy art): icon UI Display for vector art, 1 for on + * @returns {DocumentFragment|HTMLElement} + */ +App.Art.SlaveArtElement = function(artSlave, artSize, UIDisplay) { + const imageChoice = State.variables.imageChoice; + if (artSlave.custom.image !== null && artSlave.custom.image.filename !== "") { + return App.Art.customArtElement(artSlave, artSize); + } else if (imageChoice === 1) { /* VECTOR ART BY NOX/DEEPMURK */ + return App.Art.vectorArtElement(artSlave, artSize); + } else if (imageChoice === 2) { /* VECTOR ART BY NOX - Pregmod Legacy Version */ + return App.Art.legacyVectorArtElement(artSlave, UIDisplay); + } else if (imageChoice === 3) { /* VECTOR ART REVAMP*/ + return App.Art.revampedVectorArtElement(artSlave); + } else { /* RENDERED IMAGES BY SHOKUSHU */ + return App.Art.renderedArtElement(artSlave, artSize); + } +}; + window.ArtControlRendered = function ArtControlRendered(slave, sizePlacement) { + return App.Art.elementToMarkup(App.Art.renderedArtElement(slave, sizePlacement)); +}; + +/** + * @param {App.Entity.SlaveState} slave + * @param {number} imageSize + * @returns {string} + */ +window.CustomArt = function(slave, imageSize) { + return App.Art.elementToMarkup(App.Art.customArtElement(slave, imageSize)); +}; + +/** + * @param {App.Entity.SlaveState} slave + * @param {number} artSize + * @returns {HTMLElement} + */ +App.Art.renderedArtElement = function(slave, artSize) { const V = State.variables; - let fileName = "'resources/renders/"; + let fileName = "resources/renders/"; if (slave.belly > 1500) { fileName += "preg "; @@ -74,7 +117,7 @@ window.ArtControlRendered = function ArtControlRendered(slave, sizePlacement) { } } else if (slave.fetish === "mindbroken") { fileName = `${fileName} reluctant`; - } else if (slave.devotion <= 50 || slave.fetishKnown !== 1 || (V.seeMainFetishes === 0 && sizePlacement < 2)) { + } else if (slave.devotion <= 50 || slave.fetishKnown !== 1 || (V.seeMainFetishes === 0 && artSize < 2)) { fileName = `${fileName} obedient`; } else { if (slave.fetish === "none") { @@ -83,38 +126,55 @@ window.ArtControlRendered = function ArtControlRendered(slave, sizePlacement) { fileName = `${fileName} ${slave.fetish}`; } } + fileName += ".png"; - fileName += ".png'"; - if (sizePlacement === 3) { - return `<img src=${fileName} style='float:right; border:3px hidden'>`; - } else if (sizePlacement === 2) { - return `<img src=${fileName} style='float:right; border:3px hidden' width='300' height='300'>`; - } else if (sizePlacement === 1) { - return `<img src=${fileName} style='float:left; border:3px hidden' width='150' height='150'>`; - } else { - return `<img src=${fileName} style='float:left; border:3px hidden' width='120' height='120'>`; + const res = document.createElement("img"); + res.setAttribute("src", fileName); + const sz = this.artSizeToPx(artSize); + if (sz) { + res.setAttribute("width", sz); + res.setAttribute("height", sz); } -}; + return res; +} /** * @param {App.Entity.SlaveState} slave * @param {number} imageSize - * @returns {string} + * @returns {HTMLElement} */ -window.CustomArt = function(slave, imageSize) { +App.Art.customArtElement = function(slave, imageSize) { const fileType = slave.custom.image.format || "png"; - const fileName = `'resources/${slave.custom.image.filename}.${fileType}'`; - const displayTypeStart = (fileType === "webm" ? "video loop autoplay" : "img"); - const displayTypeEnd = (fileType === "webm" ? "</video>" : ""); + const fileName = `resources/${slave.custom.image.filename}.${fileType}`; + const elementType = fileType === "webm" ? "video" : "img"; + const attributes = fileType === "webm" ? ["loop", "autoplay"] : []; - if (imageSize === 3) { - return `<${displayTypeStart} src=${fileName} style='float:right; border:3px hidden'>${displayTypeEnd}`; - } else if (imageSize === 2) { - return `<${displayTypeStart} src=${fileName} style='float:right; border:3px hidden' width='300' height='300'>${displayTypeEnd}`; - } else if (imageSize === 1) { - return `<${displayTypeStart} src=${fileName} style='float:right; border:3px hidden' width='150' height='150'>${displayTypeEnd}`; - } else { - return `<${displayTypeStart} src=${fileName} style='float:right; border:3px hidden' width='120' height='120'>${displayTypeEnd}`; + const res = document.createElement(elementType); + attributes.forEach((an) => { + res.setAttribute(an, ""); + }); + + res.setAttribute("src", fileName); + res.setAttribute("style", "'float:right; border:3px hidden'"); + + const sz = this.artSizeToPx(imageSize); + if (sz) { + res.setAttribute("width", sz); + res.setAttribute("height", sz); + } + return res; +}; + +App.Art.artSizeToPx = function(artSize) { + switch (artSize) { + case 3: + return null; + case 2: + return "300"; + case 1: + return "150"; + default: + return "120"; } }; @@ -1815,3 +1875,43 @@ window.skinColorCatcher = function(artSlave) { } return colorSlave; }; + + +App.Art.cacheArtData = function() { + /** + * @param {NodeListOf<Element>} imagePassages + * @param {Object} obj + */ + function cacheImages(imagePassages, obj) { + obj.nodes = document.createDocumentFragment(); + obj.dict = new Map(); + + for (const ip of imagePassages) { + const name = ip.attributes.getNamedItem("name").value; + let div = document.createElement("div"); + div.id = "div-" + name; + const svgData = atob(ip.innerHTML.replace(/data:image\/svg\+xml;base64,/, '')); + div.innerHTML = svgData; + obj.nodes.appendChild(div); + obj.dict.set(name, obj.dict.size); + } + } + App.Data.Art = {}; + + App.Data.Art.Vector = {}; + cacheImages(document.querySelectorAll('[tags="Twine.image"][name^="Art_Vector"]:not([ame^="Art_Vector_Revamp"])'), App.Data.Art.Vector); + App.Data.Art.VectorRevamp = {}; + cacheImages(document.querySelectorAll('[tags="Twine.image"][name^="Art_Vector_Revamp"]'), App.Data.Art.VectorRevamp); +}; + +/** + * @param {Element|DocumentFragment} e + * @returns {string} + */ +App.Art.elementToMarkup = function(e) { + const div = document.createElement("div"); + div.appendChild(e); + // stripping <div>...</div>. This is probably not the wiser approach + let s = div.outerHTML; + return s.substr(5, s.length - 11); +}; diff --git a/src/art/vector/VectorArtJS.js b/src/art/vector/VectorArtJS.js index e208250d74e2e01ab89cc766c876c0ad7a43f7fe..2ffbc4002047ec8c59b788154d8f755f6e17dccd 100644 --- a/src/art/vector/VectorArtJS.js +++ b/src/art/vector/VectorArtJS.js @@ -1,11 +1,20 @@ -window.VectorArt = (function() { +window.VectorArt = function(artSlave, artSize) { + return App.Art.elementToMarkup(App.Art.SlaveArtElement(artSlave, artSize)); +}; + +window.LegacyVectorArt = function(slave, artSize) { + return App.Art.elementToMarkup(App.Art.legacyVectorArtElement(slave, artSize)); +}; + +App.Art.vectorArtElement = (function() { "use strict"; let V, T, slave; - let r; let leftArmType, rightArmType, legSize, torsoSize, buttSize, penisSize, hairLength, wearingLatex; let bellyScaleFactor, artBoobScaleFactor, heightScaleFactor; let artTranslationX, artTranslationY; - let penisDrawtime, penisArtString; + let penisDrawtime, penisArt; + /** @type {DocumentFragment} */ + let res; function VectorArt(artSlave, artSize) { /* set constants */ @@ -19,6 +28,7 @@ window.VectorArt = (function() { // eslint-disable-next-line camelcase T.art_transform = ""; /* in case other files are trying to use this, and expecting a string */ + res = document.createDocumentFragment(); setStylesheet(artSize); /* initializes the stylesheet, and r */ setArmType(); setBoobScaling(); @@ -54,13 +64,13 @@ window.VectorArt = (function() { ArtVectorBalls(); } if (penisDrawtime === 0) { /* for dicks behind boobs */ - r += penisArtString; + res.appendChild(penisArt); } ArtVectorBelly(); /* includes navel piercing and belly-related clothing options */ ArtVectorBoob(); /* includes areolae and piercings */ if (penisDrawtime === 1) { /* for dicks in front of boobs */ - r += penisArtString; + res.appendChild(penisArt); } ArtVectorBoobAddons(); /* piercings always appear in front of boobs AND dick */ @@ -68,7 +78,35 @@ window.VectorArt = (function() { ArtVectorHead(); /* glasses are drawn here */ ArtVectorHairFore(); - return r; + return res; + } + + function useSvg(id) { + const cache = App.Data.Art.Vector; + /** @type {HTMLElement} */ + const res = cache.nodes.children.item(cache.dict.get(id)).children.item(0).cloneNode(true); + res.setAttribute("class", T.art_display_class); + let transformNodes = res.querySelectorAll('g[data-transform]'); + for (const node of transformNodes) { + switch (node.getAttribute("data-transform")) { + case "boob": + node.setAttribute("transform", T.artTransformBoob); + break; + case "belly": + node.setAttribute("transform", T.artTransformBelly); + break; + case "balls": + node.setAttribute("transform", T.artTransformBalls); + break; + case "art": + if (T.art_transform) { + node.setAttribute("transform", T.art_transform); + } + break; + } + } + + return res; } function setStylesheet(artSize) { @@ -106,7 +144,8 @@ window.VectorArt = (function() { margin = Math.max(50 - (50 * slaveHeightScale), 0); } - r = `<style>.${displayClass} {\ + let st = document.createElement("style"); + st.innerHTML = `.${displayClass} {\ position: absolute;\ height: 100%;\ transform: scale(${slaveHeightScale});\ @@ -142,7 +181,8 @@ window.VectorArt = (function() { .${displayClass} .glasses{ fill:${T.glassesColor}; }\ .${displayClass} .eye{ fill:${T.eyeColor}; }\ .${displayClass} .sclera{ fill:${T.sclerae}; }\ - </style>`; + `; + res.appendChild(st); } function setArmType() { @@ -262,7 +302,7 @@ window.VectorArt = (function() { } function penisArtControl() { - penisArtString = ""; + penisArt = document.createDocumentFragment(); if (penisSize === undefined) { penisDrawtime = -1; /* no penis to draw */ } else if (State.variables.showClothingErection) { @@ -302,7 +342,7 @@ window.VectorArt = (function() { case "a toga": case "a penitent nuns habit": if ((canAchieveErection(slave)) && (slave.chastityPenis !== 1)) { - penisArtString = jsInclude(`Art_Vector_Bulge_Outfit_Hard_${penisSize}`); + penisArt.appendChild(useSvg(`Art_Vector_Bulge_Outfit_Hard_${penisSize}`)); break; /* IN CASE OF NO ERECTION, SKIP TO A NORMAL BULGE */ // FIXME: having a break in an if is bad code } /* BULGE OUTFITS LONG OUTFITS */ @@ -338,7 +378,7 @@ window.VectorArt = (function() { case "a tank-top and panties": case "conservative clothing": case "stretch pants and a crop-top": - penisArtString = jsInclude(`Art_Vector_Bulge_Outfit_${penisSize}`); + penisArt.appendChild(useSvg(`Art_Vector_Bulge_Outfit_${penisSize}`)); break; /* SMALL BULGE ONLY (SHORT) OUTFITS */ case "boyshorts": @@ -360,9 +400,9 @@ window.VectorArt = (function() { case "harem gauze": if (slave.belly <= 4000) { if (slave.dick > 3) { - penisArtString = jsInclude("Art_Vector_Bulge_Outfit_3"); + penisArt.appendChild(useSvg("Art_Vector_Bulge_Outfit_3")); } else { - penisArtString = jsInclude(`Art_Vector_Bulge_Outfit_${penisSize}`); + penisArt.appendChild(useSvg(`Art_Vector_Bulge_Outfit_${penisSize}`)); } } break; @@ -377,21 +417,21 @@ window.VectorArt = (function() { penisDrawtime = 1; /* draw erect penis over boobs if boobs do not hide the penis' base */ if (artBoobScaleFactor < 3.7) { if (slave.foreskin !== 0) { - penisArtString = jsInclude(`Art_Vector_Penis_${penisSize}`); + penisArt.appendChild(useSvg(`Art_Vector_Penis_${penisSize}`)); } else { - penisArtString = jsInclude(`Art_Vector_PenisCirc_${penisSize}`); + penisArt.appendChild(useSvg(`Art_Vector_PenisCirc_${penisSize}`)); } } } else { /* flaccid penises are drawn behind the boobs/belly */ if (slave.foreskin !== 0) { - penisArtString = jsInclude(`Art_Vector_Flaccid_${penisSize}`); + penisArt.appendChild(useSvg(`Art_Vector_Flaccid_${penisSize}`)); } else { - penisArtString = jsInclude(`Art_Vector_FlaccidCirc_${penisSize}`); + penisArt.appendChild(useSvg(`Art_Vector_FlaccidCirc_${penisSize}`)); } /* this draws chastity OVER latex catsuit. prndev finds this alright. */ if (slave.chastityPenis === 1) { - penisArtString += jsInclude(`Art_Vector_Chastity_Cage_${penisSize}`); + penisArt.appendChild(useSvg(`Art_Vector_Chastity_Cage_${penisSize}`)); } } } @@ -441,7 +481,7 @@ window.VectorArt = (function() { case "sport shorts and a sports bra": case "sport shorts and a t-shirt": case "stretch pants and a crop-top": - penisArtString = jsInclude(`Art_Vector_Bulge_Outfit_${penisSize}`); + penisArt.appendChild(useSvg(`Art_Vector_Bulge_Outfit_${penisSize}`)); break; /* BULGE OUTFITS SHORT OUTFITS */ case "a bunny outfit": @@ -479,9 +519,9 @@ window.VectorArt = (function() { case "striped underwear": if (slave.belly <= 4000) { if (slave.dick > 3) { - penisArtString = jsInclude("Art_Vector_Bulge_Outfit_3"); + penisArt.appendChild(useSvg("Art_Vector_Bulge_Outfit_3")); } else { - penisArtString = jsInclude(`Art_Vector_Bulge_Outfit_${penisSize}`); + penisArt.appendChild(useSvg(`Art_Vector_Bulge_Outfit_${penisSize}`)); } } break; @@ -497,21 +537,21 @@ window.VectorArt = (function() { penisDrawtime = 1; /* draw erect penis over boobs if boobs do not hide the penis' base */ if (artBoobScaleFactor < 3.7) { if (slave.foreskin !== 0) { - penisArtString = jsInclude(`Art_Vector_Penis_${penisSize}`); + penisArt.appendChild(useSvg(`Art_Vector_Penis_${penisSize}`)); } else { - penisArtString = jsInclude(`Art_Vector_PenisCirc_${penisSize}`); + penisArt.appendChild(useSvg(`Art_Vector_PenisCirc_${penisSize}`)); } } } else { /* flaccid penises are drawn behind the boobs/belly */ if (slave.foreskin !== 0) { - penisArtString = jsInclude(`Art_Vector_Flaccid_${penisSize}`); + penisArt.appendChild(useSvg(`Art_Vector_Flaccid_${penisSize}`)); } else { - penisArtString = jsInclude(`Art_Vector_FlaccidCirc_${penisSize}`); + penisArt.appendChild(useSvg(`Art_Vector_FlaccidCirc_${penisSize}`)); } /* this draws chastity OVER latex catsuit. prndev finds this alright. */ if (slave.chastityPenis === 1) { - penisArtString += jsInclude(`Art_Vector_Chastity_Cage_${penisSize}`); + penisArt.appendChild(useSvg(`Art_Vector_Chastity_Cage_${penisSize}`)); } } } @@ -607,21 +647,21 @@ window.VectorArt = (function() { function ArtVectorAnalAccessories() { if (slave.buttplug === "long plug") { - r += jsInclude("Art_Vector_Plug_Long"); + res.appendChild(useSvg("Art_Vector_Plug_Long")); } else if (slave.buttplug === "large plug") { - r += jsInclude("Art_Vector_Plug_Large"); + res.appendChild(useSvg("Art_Vector_Plug_Large")); } else if (slave.buttplug === "long, large plug") { - r += jsInclude("Art_Vector_Plug_Large_Long"); + res.appendChild(useSvg("Art_Vector_Plug_Large_Long")); } else if (slave.buttplug === "huge plug") { - r += jsInclude("Art_Vector_Plug_Huge"); + res.appendChild(useSvg("Art_Vector_Plug_Huge")); } else if (slave.buttplug === "long, huge plug") { - r += jsInclude("Art_Vector_Plug_Huge_Long"); + res.appendChild(useSvg("Art_Vector_Plug_Huge_Long")); } if (slave.buttplugAttachment === "tail") { - r += jsInclude("Art_Vector_Plug_Tail"); + res.appendChild(useSvg("Art_Vector_Plug_Tail")); } else if (slave.buttplugAttachment === "cat tail") { - r += jsInclude("Art_Vector_Cat_Tail"); + res.appendChild(useSvg("Art_Vector_Cat_Tail")); } } @@ -632,48 +672,48 @@ window.VectorArt = (function() { /* - added brackets to make boolean logic run */ if (slave.amp === 1) { /* Many amputee clothing art files exist, but draw nothing.They are excluded for now to reduce on rendering time - r += jsInclude("Art_Vector_Arm_Right_None"); - r += jsInclude("Art_Vector_Arm_Left_None"); + res.appendChild(useSvg("Art_Vector_Arm_Right_None")); + res.appendChild(useSvg("Art_Vector_Arm_Left_None")); */ } else { /* is not amputee or has limbs equipped so running arm calculation block */ if (slave.amp === 0) { - r += jsInclude(`Art_Vector_Arm_Right_${rightArmType}`); - r += jsInclude(`Art_Vector_Arm_Left_${leftArmType}`); + res.appendChild(useSvg(`Art_Vector_Arm_Right_${rightArmType}`)); + res.appendChild(useSvg(`Art_Vector_Arm_Left_${leftArmType}`)); if (slave.muscles >= 6) { if (leftArmType === "High") { - r += jsInclude("Art_Vector_Arm_Left_High_MLight"); + res.appendChild(useSvg("Art_Vector_Arm_Left_High_MLight")); } else if (leftArmType === "Mid") { - r += jsInclude("Art_Vector_Arm_Left_Mid_MLight"); + res.appendChild(useSvg("Art_Vector_Arm_Left_Mid_MLight")); } else if (leftArmType === "Low") { - r += jsInclude("Art_Vector_Arm_Left_Low_MLight"); + res.appendChild(useSvg("Art_Vector_Arm_Left_Low_MLight")); } else if (leftArmType === "Rebel") { - r += jsInclude("Art_Vector_Arm_Left_Rebel_MLight"); + res.appendChild(useSvg("Art_Vector_Arm_Left_Rebel_MLight")); } if (rightArmType === "High") { - r += jsInclude("Art_Vector_Arm_Right_High_MLight"); + res.appendChild(useSvg("Art_Vector_Arm_Right_High_MLight")); } else if (rightArmType === "Mid") { - r += jsInclude("Art_Vector_Arm_Right_Mid_MLight"); + res.appendChild(useSvg("Art_Vector_Arm_Right_Mid_MLight")); } else if (rightArmType === "Low") { - r += jsInclude("Art_Vector_Arm_Right_Low_MLight"); + res.appendChild(useSvg("Art_Vector_Arm_Right_Low_MLight")); } } } else if (slave.PLimb === 1 || slave.PLimb === 2) { /* slave is an amputee and has PLimbs equipped */ if (slave.amp === -1) { - r += jsInclude(`Art_Vector_Arm_Right_ProstheticBasic_${rightArmType}`); - r += jsInclude(`Art_Vector_Arm_Left_ProstheticBasic_${leftArmType}`); + res.appendChild(useSvg(`Art_Vector_Arm_Right_ProstheticBasic_${rightArmType}`)); + res.appendChild(useSvg(`Art_Vector_Arm_Left_ProstheticBasic_${leftArmType}`)); } else if (slave.amp === -2) { - r += jsInclude(`Art_Vector_Arm_Right_ProstheticSexy_${rightArmType}`); - r += jsInclude(`Art_Vector_Arm_Left_ProstheticSexy_${leftArmType}`); + res.appendChild(useSvg(`Art_Vector_Arm_Right_ProstheticSexy_${rightArmType}`)); + res.appendChild(useSvg(`Art_Vector_Arm_Left_ProstheticSexy_${leftArmType}`)); } else if (slave.amp === -3) { /* Reverting beauty limbs to regular SVG */ - r += jsInclude(`Art_Vector_Arm_Right_ProstheticBeauty_${rightArmType}`); - r += jsInclude(`Art_Vector_Arm_Left_ProstheticBeauty_${leftArmType}`); + res.appendChild(useSvg(`Art_Vector_Arm_Right_ProstheticBeauty_${rightArmType}`)); + res.appendChild(useSvg(`Art_Vector_Arm_Left_ProstheticBeauty_${leftArmType}`)); } else if (slave.amp === -4) { - r += jsInclude(`Art_Vector_Arm_Right_ProstheticCombat_${rightArmType}`); - r += jsInclude(`Art_Vector_Arm_Left_ProstheticCombat_${leftArmType}`); + res.appendChild(useSvg(`Art_Vector_Arm_Right_ProstheticCombat_${rightArmType}`)); + res.appendChild(useSvg(`Art_Vector_Arm_Left_ProstheticCombat_${leftArmType}`)); } else if (slave.amp === -5) { - r += jsInclude(`Art_Vector_Arm_Right_ProstheticSwiss_${rightArmType}`); - r += jsInclude(`Art_Vector_Arm_Left_ProstheticSwiss_${leftArmType}`); + res.appendChild(useSvg(`Art_Vector_Arm_Right_ProstheticSwiss_${rightArmType}`)); + res.appendChild(useSvg(`Art_Vector_Arm_Left_ProstheticSwiss_${leftArmType}`)); } } /* shiny clothing */ @@ -681,11 +721,11 @@ window.VectorArt = (function() { if (wearingLatex === true || slave.clothes === "body oil") { /* only some arm positions have art (feel free to add more) */ if (leftArmType === "High") { - r += jsInclude("Art_Vector_Arm_Outfit_Shine_Left_High"); + res.appendChild(useSvg("Art_Vector_Arm_Outfit_Shine_Left_High")); } else if (leftArmType === "Mid") { - r += jsInclude("Art_Vector_Arm_Outfit_Shine_Left_Mid"); + res.appendChild(useSvg("Art_Vector_Arm_Outfit_Shine_Left_Mid")); } else if (leftArmType === "Low") { - r += jsInclude("Art_Vector_Arm_Outfit_Shine_Left_Low"); + res.appendChild(useSvg("Art_Vector_Arm_Outfit_Shine_Left_Low")); } } } @@ -734,25 +774,25 @@ window.VectorArt = (function() { case "slutty jewelry": case "sport shorts and a t-shirt": case "Western clothing": - r += jsInclude(`Art_Vector_Arm_Outfit_${clothing2artSuffix(slave.clothes)}_Right_${rightArmType}`); - r += jsInclude(`Art_Vector_Arm_Outfit_${clothing2artSuffix(slave.clothes)}_Left_${leftArmType}`); + res.appendChild(useSvg(`Art_Vector_Arm_Outfit_${clothing2artSuffix(slave.clothes)}_Right_${rightArmType}`)); + res.appendChild(useSvg(`Art_Vector_Arm_Outfit_${clothing2artSuffix(slave.clothes)}_Left_${leftArmType}`)); break; /* manually handle special cases */ case "a schutzstaffel uniform": case "a slutty schutzstaffel uniform": - r += jsInclude(`Art_Vector_Arm_Outfit_SchutzstaffelUniform_Right_${rightArmType}`); - r += jsInclude(`Art_Vector_Arm_Outfit_SchutzstaffelUniform_Left_${leftArmType}`); + res.appendChild(useSvg(`Art_Vector_Arm_Outfit_SchutzstaffelUniform_Right_${rightArmType}`)); + res.appendChild(useSvg(`Art_Vector_Arm_Outfit_SchutzstaffelUniform_Left_${leftArmType}`)); break; case "a hijab and abaya": case "a niqab and abaya": case "a burqa": - r += jsInclude(`Art_Vector_Arm_Outfit_HijabAndAbaya_Right_${rightArmType}`); - r += jsInclude(`Art_Vector_Arm_Outfit_HijabAndAbaya_Left_${leftArmType}`); + res.appendChild(useSvg(`Art_Vector_Arm_Outfit_HijabAndAbaya_Right_${rightArmType}`)); + res.appendChild(useSvg(`Art_Vector_Arm_Outfit_HijabAndAbaya_Left_${leftArmType}`)); break; case "a slave gown": /* only some arm positions have art (feel free to add more) */ if (leftArmType !== "Rebel") { - r += jsInclude(`Art_Vector_Arm_Outfit_SlaveGown_Left_${leftArmType}`); + res.appendChild(useSvg(`Art_Vector_Arm_Outfit_SlaveGown_Left_${leftArmType}`)); } } } /* close .amp check */ @@ -790,7 +830,7 @@ window.VectorArt = (function() { artTranslationX = -271 * (ballsScaleFactor - 1); artTranslationY = -453 * (ballsScaleFactor - 1); T.artTransformBalls = `matrix(${ballsScaleFactor},0,0,${ballsScaleFactor},${artTranslationX},${artTranslationY})`; - r += jsInclude("Art_Vector_Balls"); + res.appendChild(useSvg("Art_Vector_Balls")); } } @@ -804,11 +844,11 @@ window.VectorArt = (function() { T.artTransformBelly = `matrix(${bellyScaleFactor},0,0,${bellyScaleFactor},${artTranslationX},${artTranslationY})`; if (slave.navelPiercing === 1) { - r += jsInclude("Art_Vector_Belly_Pregnant_Piercing"); + res.appendChild(useSvg("Art_Vector_Belly_Pregnant_Piercing")); } else if (slave.navelPiercing === 2) { - r += jsInclude("Art_Vector_Belly_Pregnant_Piercing_Heavy"); + res.appendChild(useSvg("Art_Vector_Belly_Pregnant_Piercing_Heavy")); } else { - r += jsInclude("Art_Vector_Belly"); + res.appendChild(useSvg("Art_Vector_Belly")); } switch (slave.clothes) { @@ -858,47 +898,47 @@ window.VectorArt = (function() { break; /* do nothing for these choices */ /* manually handle special cases */ case "a slutty schutzstaffel uniform": - r += jsInclude("Art_Vector_Belly_Outfit_SchutzstaffelUniform"); + res.appendChild(useSvg("Art_Vector_Belly_Outfit_SchutzstaffelUniform")); break; case "a niqab and abaya": case "a burqa": - r += jsInclude("Art_Vector_Belly_Outfit_HijabAndAbaya"); + res.appendChild(useSvg("Art_Vector_Belly_Outfit_HijabAndAbaya")); break; default: - r += jsInclude(`Art_Vector_Belly_Outfit_${clothing2artSuffix(slave.clothes)}`); + res.appendChild(useSvg(`Art_Vector_Belly_Outfit_${clothing2artSuffix(slave.clothes)}`)); } /* shiny clothing */ if (V.seeVectorArtHighlights === 1) { if (wearingLatex === true || slave.clothes === "body oil") { - r += jsInclude("Art_Vector_Belly_Outfit_Shine"); + res.appendChild(useSvg("Art_Vector_Belly_Outfit_Shine")); } } } /* belly piercings for flat bellies */ if (slave.belly === 0) { if (slave.navelPiercing === 1) { - r += jsInclude("Art_Vector_Belly_Piercing"); + res.appendChild(useSvg("Art_Vector_Belly_Piercing")); } else if (slave.navelPiercing === 2) { - r += jsInclude("Art_Vector_Belly_Piercing_Heavy"); + res.appendChild(useSvg("Art_Vector_Belly_Piercing_Heavy")); } } /* Torso Accessories */ if ((slave.bellyAccessory === "a corset" || slave.bellyAccessory === "an extreme corset") && slave.belly <= 1500) { if (torsoSize === "Normal") { - r += jsInclude("Art_Vector_Corsetnormal"); + res.appendChild(useSvg("Art_Vector_Corsetnormal")); } else if (torsoSize === "Hourglass") { - r += jsInclude("Art_Vector_Corsethourglass"); + res.appendChild(useSvg("Art_Vector_Corsethourglass")); } else if (torsoSize === "Unnatural") { - r += jsInclude("Art_Vector_Corsetunnatural"); + res.appendChild(useSvg("Art_Vector_Corsetunnatural")); } } else if (slave.bellyAccessory === "a small empathy belly") { - r += jsInclude("Art_Vector_Empathy_Belly_Small"); + res.appendChild(useSvg("Art_Vector_Empathy_Belly_Small")); } else if (slave.bellyAccessory === "a medium empathy belly") { - r += jsInclude("Art_Vector_Empathy_Belly_Medium"); + res.appendChild(useSvg("Art_Vector_Empathy_Belly_Medium")); } else if (slave.bellyAccessory === "a large empathy belly") { - r += jsInclude("Art_Vector_Empathy_Belly_Large"); + res.appendChild(useSvg("Art_Vector_Empathy_Belly_Large")); } else if (slave.bellyAccessory === "a huge empathy belly") { - r += jsInclude("Art_Vector_Empathy_Belly_Huge"); + res.appendChild(useSvg("Art_Vector_Empathy_Belly_Huge")); } } @@ -907,11 +947,11 @@ window.VectorArt = (function() { /* BEWARE: this threshold may be used in other art-related code, too */ /* boobs too small - draw areolae directly onto torso */ } else { - r += jsInclude("Art_Vector_Boob_Alt"); + res.appendChild(useSvg("Art_Vector_Boob_Alt")); /* shiny clothing */ if (V.seeVectorArtHighlights === 1) { if (slave.fuckdoll !== 0 || slave.clothes === "a latex catsuit" || slave.clothes === "body oil") { - r += jsInclude("Art_Vector_Boob_Outfit_Shine"); + res.appendChild(useSvg("Art_Vector_Boob_Outfit_Shine")); } } } @@ -947,33 +987,33 @@ window.VectorArt = (function() { case "striped panties": case "uncomfortable straps": if (slave.areolaeShape === "star") { - r += jsInclude("Art_Vector_Boob_Areola_Star"); + res.appendChild(useSvg("Art_Vector_Boob_Areola_Star")); } else if (slave.areolaeShape === "heart") { - r += jsInclude("Art_Vector_Boob_Areola_Heart"); + res.appendChild(useSvg("Art_Vector_Boob_Areola_Heart")); } else if (slave.areolae === 0) { - r += jsInclude("Art_Vector_Boob_Areola"); + res.appendChild(useSvg("Art_Vector_Boob_Areola")); } else if (slave.areolae === 1) { - r += jsInclude("Art_Vector_Boob_Areola_Large"); + res.appendChild(useSvg("Art_Vector_Boob_Areola_Large")); } else if (slave.areolae === 2) { - r += jsInclude("Art_Vector_Boob_Areola_Wide"); + res.appendChild(useSvg("Art_Vector_Boob_Areola_Wide")); } else if (slave.areolae >= 3) { - r += jsInclude("Art_Vector_Boob_Areola_Huge"); + res.appendChild(useSvg("Art_Vector_Boob_Areola_Huge")); } if (slave.nipples === "tiny") { - r += jsInclude("Art_Vector_Boob_NippleTiny"); + res.appendChild(useSvg("Art_Vector_Boob_NippleTiny")); } else if (slave.nipples === "cute") { - r += jsInclude("Art_Vector_Boob_NippleCute"); + res.appendChild(useSvg("Art_Vector_Boob_NippleCute")); } else if (slave.nipples === "puffy") { - r += jsInclude("Art_Vector_Boob_NipplePuffy"); + res.appendChild(useSvg("Art_Vector_Boob_NipplePuffy")); } else if (slave.nipples === "inverted") { - r += jsInclude("Art_Vector_Boob_NippleInverted"); + res.appendChild(useSvg("Art_Vector_Boob_NippleInverted")); } else if (slave.nipples === "huge") { - r += jsInclude("Art_Vector_Boob_NippleHuge"); + res.appendChild(useSvg("Art_Vector_Boob_NippleHuge")); } else if (slave.nipples === "partially inverted") { - r += jsInclude("Art_Vector_Boob_NipplePartiallyInverted"); + res.appendChild(useSvg("Art_Vector_Boob_NipplePartiallyInverted")); } else if (slave.nipples === "fuckable") { - r += jsInclude("Art_Vector_Boob_NippleFuckable"); + res.appendChild(useSvg("Art_Vector_Boob_NippleFuckable")); } } } @@ -1011,17 +1051,17 @@ window.VectorArt = (function() { break; /* do nothing for these choices */ /* manually handle special cases */ case "a slutty schutzstaffel uniform": - r += jsInclude("Art_Vector_Boob_Outfit_SchutzstaffelUniform"); + res.appendChild(useSvg("Art_Vector_Boob_Outfit_SchutzstaffelUniform")); break; case "a niqab and abaya": case "a burqa": - r += jsInclude("Art_Vector_Boob_Outfit_HijabAndAbaya"); + res.appendChild(useSvg("Art_Vector_Boob_Outfit_HijabAndAbaya")); break; case "pasties": - r += jsInclude("Art_Vector_Boob_Outfit_PantiesAndPasties"); + res.appendChild(useSvg("Art_Vector_Boob_Outfit_PantiesAndPasties")); break; default: - r += jsInclude(`Art_Vector_Boob_Outfit_${clothing2artSuffix(slave.clothes)}`); + res.appendChild(useSvg(`Art_Vector_Boob_Outfit_${clothing2artSuffix(slave.clothes)}`)); } } if (V.showBodyMods === 1 && (slave.nipplesPiercing > 0 || slave.areolaePiercing > 0)) { @@ -1063,15 +1103,15 @@ window.VectorArt = (function() { case "striped panties": case "uncomfortable straps": if (slave.nipplesPiercing === 1) { - r += jsInclude("Art_Vector_Boob_Piercing"); + res.appendChild(useSvg("Art_Vector_Boob_Piercing")); } else if (slave.nipplesPiercing > 1) { - r += jsInclude("Art_Vector_Boob_Piercing_Heavy"); + res.appendChild(useSvg("Art_Vector_Boob_Piercing_Heavy")); } if (slave.areolaePiercing === 1) { - r += jsInclude("Art_Vector_Boob_Areola_Piercing"); + res.appendChild(useSvg("Art_Vector_Boob_Areola_Piercing")); } else if (slave.areolaePiercing > 1) { - r += jsInclude("Art_Vector_Boob_Areola_Piercingheavy"); + res.appendChild(useSvg("Art_Vector_Boob_Areola_Piercingheavy")); } } } @@ -1079,17 +1119,17 @@ window.VectorArt = (function() { function ArtVectorButt() { if (slave.amp === 0) { - r += jsInclude(`Art_Vector_Butt_${buttSize}`); + res.appendChild(useSvg(`Art_Vector_Butt_${buttSize}`)); } else if (slave.amp === -1) { - r += jsInclude(`Art_Vector_Butt_ProstheticBasic_${buttSize}`); + res.appendChild(useSvg(`Art_Vector_Butt_ProstheticBasic_${buttSize}`)); } else if (slave.amp === -2) { - r += jsInclude(`Art_Vector_Butt_ProstheticSexy_${buttSize}`); + res.appendChild(useSvg(`Art_Vector_Butt_ProstheticSexy_${buttSize}`)); } else if (slave.amp === -3) { /* reverted to regular SVG to match description */ - r += jsInclude(`Art_Vector_Butt_ProstheticBeauty_${buttSize}`); + res.appendChild(useSvg(`Art_Vector_Butt_ProstheticBeauty_${buttSize}`)); } else if (slave.amp === -4) { - r += jsInclude(`Art_Vector_Butt_ProstheticCombat_${buttSize}`); + res.appendChild(useSvg(`Art_Vector_Butt_ProstheticCombat_${buttSize}`)); } else if (slave.amp === -5) { - r += jsInclude(`Art_Vector_Butt_ProstheticSwiss_${buttSize}`); + res.appendChild(useSvg(`Art_Vector_Butt_ProstheticSwiss_${buttSize}`)); } } @@ -1139,18 +1179,18 @@ window.VectorArt = (function() { if (slave.chastityAnus === 1) { if (bodySize === "Fat") { - r += jsInclude("Art_Vector_Chastity_Vagina_Fat"); + res.appendChild(useSvg("Art_Vector_Chastity_Vagina_Fat")); } else { - r += jsInclude("Art_Vector_Chastity_Anus"); - r += jsInclude(`Art_Vector_Chastity_Base${bodySize}`); + res.appendChild(useSvg("Art_Vector_Chastity_Anus")); + res.appendChild(useSvg(`Art_Vector_Chastity_Base${bodySize}`)); } } if (slave.chastityVagina === 1) { if (bodySize === "Fat") { - r += jsInclude("Art_Vector_Chastity_Vagina_Fat"); + res.appendChild(useSvg("Art_Vector_Chastity_Vagina_Fat")); } else { - r += jsInclude("Art_Vector_Chastity_Vagina"); - r += jsInclude(`Art_Vector_Chastity_Base${bodySize}`); + res.appendChild(useSvg("Art_Vector_Chastity_Vagina")); + res.appendChild(useSvg(`Art_Vector_Chastity_Base${bodySize}`)); } } if (slave.vaginalAccessory !== "none") { @@ -1203,21 +1243,21 @@ window.VectorArt = (function() { case "striped underwear": case "uncomfortable straps": if (slave.vaginalAccessory === "dildo") { - r += jsInclude("Art_Vector_Dildo_Short"); + res.appendChild(useSvg("Art_Vector_Dildo_Short")); } else if (slave.vaginalAccessory === "long dildo") { - r += jsInclude("Art_Vector_Dildo_Long"); + res.appendChild(useSvg("Art_Vector_Dildo_Long")); } else if (slave.clothes !== "a comfortable bodysuit" && slave.clothes !== "a string bikini" && slave.clothes !== "attractive lingerie for a pregnant woman" && slave.clothes !== "restrictive latex") { if (slave.vaginalAccessory === "large dildo") { /* additional outfits disabled due to the art breaking with the larger accessories */ - r += jsInclude("Art_Vector_Dildo_Large"); + res.appendChild(useSvg("Art_Vector_Dildo_Large")); } else if (slave.vaginalAccessory === "long, large dildo") { - r += jsInclude("Art_Vector_Dildo_Large_Long"); + res.appendChild(useSvg("Art_Vector_Dildo_Large_Long")); } else if (slave.vaginalAccessory === "huge dildo") { - r += jsInclude("Art_Vector_Dildo_Huge"); + res.appendChild(useSvg("Art_Vector_Dildo_Huge")); } else if (slave.vaginalAccessory === "long, huge dildo") { - r += jsInclude("Art_Vector_Dildo_Huge_Long"); + res.appendChild(useSvg("Art_Vector_Dildo_Huge_Long")); } } /* else if (slave.vaginalAccessory === "bullet vibrator" || slave.vaginalAccessory === "smart bullet vibrator") { - r += jsInclude("Art_Vector_Bullet_Vibrator"); + res.appendChild(useSvg("Art_Vector_Bullet_Vibrator")); } */ } } @@ -1621,50 +1661,50 @@ window.VectorArt = (function() { } function ArtVectorCollar() { - r += jsInclude("Art_Vector_Clavicle"); + res.appendChild(useSvg("Art_Vector_Clavicle")); /* TODO: find out where "uncomfortable leather" collar art went */ switch (slave.collar) { case "leather with cowbell": - r += jsInclude("Art_Vector_Collar_Cowbell"); + res.appendChild(useSvg("Art_Vector_Collar_Cowbell")); break; case "heavy gold": - r += jsInclude("Art_Vector_Collar_Gold_Heavy"); + res.appendChild(useSvg("Art_Vector_Collar_Gold_Heavy")); break; case "neck corset": - r += jsInclude("Art_Vector_Collar_Neck_Corset"); + res.appendChild(useSvg("Art_Vector_Collar_Neck_Corset")); break; case "pretty jewelry": - r += jsInclude("Art_Vector_Collar_Pretty_Jewelry"); + res.appendChild(useSvg("Art_Vector_Collar_Pretty_Jewelry")); break; case "cruel retirement counter": - r += jsInclude("Art_Vector_Collar_Retirement_Cruel"); + res.appendChild(useSvg("Art_Vector_Collar_Retirement_Cruel")); break; case "nice retirement counter": - r += jsInclude("Art_Vector_Collar_Retirement_Nice"); + res.appendChild(useSvg("Art_Vector_Collar_Retirement_Nice")); break; case "satin choker": - r += jsInclude("Art_Vector_Collar_Satin_Choker"); + res.appendChild(useSvg("Art_Vector_Collar_Satin_Choker")); break; case "shock punishment": - r += jsInclude("Art_Vector_Collar_Shock_Punishment"); + res.appendChild(useSvg("Art_Vector_Collar_Shock_Punishment")); break; case "stylish leather": - r += jsInclude("Art_Vector_Collar_Stylish_Leather"); + res.appendChild(useSvg("Art_Vector_Collar_Stylish_Leather")); break; case "tight steel": - r += jsInclude("Art_Vector_Collar_Tight_Steel"); + res.appendChild(useSvg("Art_Vector_Collar_Tight_Steel")); break; case "uncomfortable leather": - r += jsInclude("Art_Vector_Collar_Leather_Cruel"); + res.appendChild(useSvg("Art_Vector_Collar_Leather_Cruel")); break; case "silk ribbon": - r += jsInclude("Art_Vector_Collar_Silk_Ribbon"); + res.appendChild(useSvg("Art_Vector_Collar_Silk_Ribbon")); break; case "bowtie": - r += jsInclude("Art_Vector_Collar_Bowtie"); + res.appendChild(useSvg("Art_Vector_Collar_Bowtie")); break; case "ancient Egyptian": - r += jsInclude("Art_Vector_Collar_Ancientegyptian"); + res.appendChild(useSvg("Art_Vector_Collar_Ancientegyptian")); } } @@ -1679,41 +1719,41 @@ window.VectorArt = (function() { /* Updated 2018-10-25 by Fr0g */ /* - added brackets to make boolean logic run */ if (slave.shoes === "heels") { - r += jsInclude("Art_Vector_Shoes_Heel"); + res.appendChild(useSvg("Art_Vector_Shoes_Heel")); } else if (slave.shoes === "pumps") { - r += jsInclude("Art_Vector_Shoes_Pump"); + res.appendChild(useSvg("Art_Vector_Shoes_Pump")); } else if (slave.shoes === "extreme heels") { - r += jsInclude(`Art_Vector_Shoes_Extreme_Heel_${legSize}`); + res.appendChild(useSvg(`Art_Vector_Shoes_Extreme_Heel_${legSize}`)); } else if (slave.shoes === "boots") { - r += jsInclude(`Art_Vector_Shoes_Boot_${legSize}`); + res.appendChild(useSvg(`Art_Vector_Shoes_Boot_${legSize}`)); } else if (slave.shoes === "flats") { - r += jsInclude("Art_Vector_Shoes_Flat"); + res.appendChild(useSvg("Art_Vector_Shoes_Flat")); } else { if (slave.amp === 0) { - r += jsInclude("Art_Vector_Feet_Normal"); + res.appendChild(useSvg("Art_Vector_Feet_Normal")); } else if (slave.PLimb === 1 || slave.PLimb === 2) { if (slave.amp === -1) { - r += jsInclude("Art_Vector_Feet_ProstheticBasic"); + res.appendChild(useSvg("Art_Vector_Feet_ProstheticBasic")); } else if (slave.amp === -2) { - r += jsInclude("Art_Vector_Feet_ProstheticSexy"); + res.appendChild(useSvg("Art_Vector_Feet_ProstheticSexy")); } else if (slave.amp === -3) { - r += jsInclude("Art_Vector_Feet_ProstheticBeauty"); + res.appendChild(useSvg("Art_Vector_Feet_ProstheticBeauty")); } else if (slave.amp === -4) { - r += jsInclude("Art_Vector_Feet_ProstheticCombat"); + res.appendChild(useSvg("Art_Vector_Feet_ProstheticCombat")); } else if (slave.amp === -5) { - r += jsInclude("Art_Vector_Feet_ProstheticSwiss"); + res.appendChild(useSvg("Art_Vector_Feet_ProstheticSwiss")); } } } if (stockings !== undefined && slave.amp !== 1) { if (slave.shoes === "heels") { - r += jsInclude(`Art_Vector_Shoes_Heel_${stockings}_${legSize}`); + res.appendChild(useSvg(`Art_Vector_Shoes_Heel_${stockings}_${legSize}`)); } else if (slave.shoes === "pumps") { - r += jsInclude(`Art_Vector_Shoes_Pump_${stockings}_${legSize}`); + res.appendChild(useSvg(`Art_Vector_Shoes_Pump_${stockings}_${legSize}`)); } else if (slave.shoes === "flats") { - r += jsInclude(`Art_Vector_Shoes_Flat_${stockings}_${legSize}`); + res.appendChild(useSvg(`Art_Vector_Shoes_Flat_${stockings}_${legSize}`)); } else if (slave.shoes === "none") { - r += jsInclude(`Art_Vector_Shoes_Stockings_${stockings}_${legSize}`); + res.appendChild(useSvg(`Art_Vector_Shoes_Stockings_${stockings}_${legSize}`)); } } switch (slave.clothes) { @@ -1777,14 +1817,14 @@ window.VectorArt = (function() { if (outfit !== undefined) { if (slave.amp !== 1) { if (slave.clothes !== "a slutty qipao" && slave.clothes !== "harem gauze" && slave.clothes !== "slutty jewelry" && slave.clothes !== "Western clothing") { /* these clothes have a stump/leg outfit, but no butt outfit */ - r += jsInclude(`Art_Vector_Butt_Outfit_${outfit}_${buttSize}`); + res.appendChild(useSvg(`Art_Vector_Butt_Outfit_${outfit}_${buttSize}`)); } if (slave.clothes !== "a schoolgirl outfit") { /* file is there, but contains no artwork */ - r += jsInclude(`Art_Vector_Leg_Outfit_${outfit}_${legSize}`); + res.appendChild(useSvg(`Art_Vector_Leg_Outfit_${outfit}_${legSize}`)); } } else { if (outfit === "Shine") { /* the only stump outfit that does not draw an empty svg */ - r += jsInclude(`Art_Vector_Leg_Outfit_${outfit}_Stump`); + res.appendChild(useSvg(`Art_Vector_Leg_Outfit_${outfit}_Stump`)); } } } @@ -1793,7 +1833,7 @@ window.VectorArt = (function() { function ArtVectorHairBack() { if (hairLength !== undefined) { /* Don't draw hair if it isn't there */ if (slave.fuckdoll !== 0 || (slave.bald !== 0 && slave.hStyle === "bald")) { - r += jsInclude("Art_Vector_Hair_Back_NoHair"); + res.appendChild(useSvg("Art_Vector_Hair_Back_NoHair")); } else { switch (slave.clothes) { case "a biyelgee costume": @@ -1824,20 +1864,20 @@ window.VectorArt = (function() { case "buzzcut": case "shaved": case "shaved bald": - r += jsInclude("Art_Vector_Hair_Back_NoHair"); + res.appendChild(useSvg("Art_Vector_Hair_Back_NoHair")); break; case "afro": if (slave.hLength >= 150) { - r += jsInclude("Art_Vector_Hair_Back_Afro_Giant"); + res.appendChild(useSvg("Art_Vector_Hair_Back_Afro_Giant")); } else { - r += jsInclude(`Art_Vector_Hair_Back_Afro_${hairLength}`); + res.appendChild(useSvg(`Art_Vector_Hair_Back_Afro_${hairLength}`)); } break; case "messy bun": - r += jsInclude(`Art_Vector_Hair_Back_Ninja_${hairLength}`); + res.appendChild(useSvg(`Art_Vector_Hair_Back_Ninja_${hairLength}`)); break; case "strip": - r += jsInclude("Art_Vector_Hair_Back_NoHair"); + res.appendChild(useSvg("Art_Vector_Hair_Back_NoHair")); break; case "braided": case "bun": @@ -1852,24 +1892,24 @@ window.VectorArt = (function() { case "ponytail": case "tails": case "up": - r += jsInclude(`Art_Vector_Hair_Back_${capFirstChar(slave.hStyle)}_${hairLength}`); + res.appendChild(useSvg(`Art_Vector_Hair_Back_${capFirstChar(slave.hStyle)}_${hairLength}`)); break; default: - r += jsInclude("Art_Vector_Hair_Back_Messy_Medium"); + res.appendChild(useSvg("Art_Vector_Hair_Back_Messy_Medium")); } } } } /* note: latex clothing actually shows some hair, but there is no appropriate art for it */ if (slave.collar === "cat ears") { - r += jsInclude("Art_Vector_Cat_Ear_Back"); + res.appendChild(useSvg("Art_Vector_Cat_Ear_Back")); } } function ArtVectorHairFore() { if (hairLength !== undefined) { /* Don't draw hair if it isn't there */ if (slave.fuckdoll !== 0 || (slave.bald !== 0 && slave.hStyle === "bald")) { - r += jsInclude("Art_Vector_Hair_Fore_NoHair"); + res.appendChild(useSvg("Art_Vector_Hair_Fore_NoHair")); } else { switch (slave.clothes) { case "a biyelgee costume": @@ -1900,22 +1940,22 @@ window.VectorArt = (function() { case "buzzcut": case "shaved": case "shaved bald": - r += jsInclude("Art_Vector_Hair_Fore_NoHair"); + res.appendChild(useSvg("Art_Vector_Hair_Fore_NoHair")); break; case "afro": if (slave.hLength >= 150) { - r += jsInclude("Art_Vector_Hair_Fore_Afro_Giant"); + res.appendChild(useSvg("Art_Vector_Hair_Fore_Afro_Giant")); } else { - r += jsInclude(`Art_Vector_Hair_Fore_Afro_${hairLength}`); + res.appendChild(useSvg(`Art_Vector_Hair_Fore_Afro_${hairLength}`)); } break; case "messy bun": - r += jsInclude(`Art_Vector_Hair_Fore_Ninja_${hairLength}`); + res.appendChild(useSvg(`Art_Vector_Hair_Fore_Ninja_${hairLength}`)); break; case "bun": case "neat": case "ponytail": - r += jsInclude(`Art_Vector_Hair_Fore_${capFirstChar(slave.hStyle)}`); + res.appendChild(useSvg(`Art_Vector_Hair_Fore_${capFirstChar(slave.hStyle)}`)); break; case "braided": case "cornrows": @@ -1928,17 +1968,17 @@ window.VectorArt = (function() { case "strip": case "tails": case "up": - r += jsInclude(`Art_Vector_Hair_Fore_${capFirstChar(slave.hStyle)}_${hairLength}`); + res.appendChild(useSvg(`Art_Vector_Hair_Fore_${capFirstChar(slave.hStyle)}_${hairLength}`)); break; default: - r += jsInclude("Art_Vector_Hair_Fore_Messy_Medium"); + res.appendChild(useSvg("Art_Vector_Hair_Fore_Messy_Medium")); } } } } /* note: latex clothing actually shows some hair, but there is no appropriate art for it */ if (slave.collar === "cat ears") { - r += jsInclude("Art_Vector_Cat_Ear_Fore"); + res.appendChild(useSvg("Art_Vector_Cat_Ear_Fore")); } } @@ -1946,24 +1986,24 @@ window.VectorArt = (function() { const eyebrowFullness = clothing2artSuffix(slave.eyebrowFullness); /* designed for clothing but works for eyebrows too. If other eyebrow styles are added, this may need to be changed. */ const hasEyebrows = slave.eyebrowHStyle !== "bald" && slave.eyebrowHStyle !== "shaved"; - r += jsInclude("Art_Vector_Head"); + res.appendChild(useSvg("Art_Vector_Head")); /* shiny clothing */ if (V.seeVectorArtHighlights === 1) { if (wearingLatex === true) { - r += jsInclude("Art_Vector_Head_Outfit_Shine"); + res.appendChild(useSvg("Art_Vector_Head_Outfit_Shine")); } } if (slave.clothes !== "restrictive latex") { if (slave.markings === "beauty mark") { - r += jsInclude("Art_Vector_Beauty_Mark"); + res.appendChild(useSvg("Art_Vector_Beauty_Mark")); } else if (slave.markings === "freckles") { - r += jsInclude("Art_Vector_Freckles"); + res.appendChild(useSvg("Art_Vector_Freckles")); } else if (slave.markings === "heavily freckled") { - r += jsInclude("Art_Vector_Freckles_Heavy"); + res.appendChild(useSvg("Art_Vector_Freckles_Heavy")); } else if (slave.markings === "birthmark") { - r += jsInclude("Art_Vector_Birthmark"); + res.appendChild(useSvg("Art_Vector_Birthmark")); } else if (slave.minorInjury === "black eye") { - r += jsInclude("Art_Vector_Black_Eye"); + res.appendChild(useSvg("Art_Vector_Black_Eye")); } } /* FACIAL APPEARANCE */ @@ -1973,46 +2013,46 @@ window.VectorArt = (function() { case "southern european": case "white": if (slave.faceShape === "normal") { - r += jsInclude("Art_Vector_Eyes_TypeB"); - r += jsInclude("Art_Vector_Mouth_TypeA"); - r += jsInclude("Art_Vector_Nose_TypeA"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeB")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeA")); + res.appendChild(useSvg("Art_Vector_Nose_TypeA")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeA_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeA_${eyebrowFullness}`)); } } else if (slave.faceShape === "masculine") { - r += jsInclude("Art_Vector_Eyes_TypeD"); - r += jsInclude("Art_Vector_Mouth_TypeF"); - r += jsInclude("Art_Vector_Nose_TypeF"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeD")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeF")); + res.appendChild(useSvg("Art_Vector_Nose_TypeF")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeE_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeE_${eyebrowFullness}`)); } } else if (slave.faceShape === "androgynous") { - r += jsInclude("Art_Vector_Eyes_TypeE"); - r += jsInclude("Art_Vector_Mouth_TypeE"); - r += jsInclude("Art_Vector_Nose_TypeE"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeE")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeE")); + res.appendChild(useSvg("Art_Vector_Nose_TypeE")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeF_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeF_${eyebrowFullness}`)); } } else if (slave.faceShape === "cute") { - r += jsInclude("Art_Vector_Eyes_TypeB"); - r += jsInclude("Art_Vector_Mouth_TypeB"); - r += jsInclude("Art_Vector_Nose_TypeD"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeB")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeB")); + res.appendChild(useSvg("Art_Vector_Nose_TypeD")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeA_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeA_${eyebrowFullness}`)); } } else if (slave.faceShape === "sensual") { - r += jsInclude("Art_Vector_Eyes_TypeC"); - r += jsInclude("Art_Vector_Mouth_TypeC"); - r += jsInclude("Art_Vector_Nose_TypeC"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeC")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeC")); + res.appendChild(useSvg("Art_Vector_Nose_TypeC")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`)); } } else if (slave.faceShape === "exotic") { - r += jsInclude("Art_Vector_Eyes_TypeA"); - r += jsInclude("Art_Vector_Mouth_TypeC"); - r += jsInclude("Art_Vector_Nose_TypeC"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeA")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeC")); + res.appendChild(useSvg("Art_Vector_Nose_TypeC")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`)); } } break; @@ -2020,366 +2060,366 @@ window.VectorArt = (function() { case "malay": case "pacific islander": if (slave.faceShape === "normal") { - r += jsInclude("Art_Vector_Eyes_TypeA"); - r += jsInclude("Art_Vector_Mouth_TypeC"); - r += jsInclude("Art_Vector_Nose_TypeC"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeA")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeC")); + res.appendChild(useSvg("Art_Vector_Nose_TypeC")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeD_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeD_${eyebrowFullness}`)); } } else if (slave.faceShape === "masculine") { - r += jsInclude("Art_Vector_Eyes_TypeD"); - r += jsInclude("Art_Vector_Mouth_TypeD"); - r += jsInclude("Art_Vector_Nose_TypeB"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeD")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeD")); + res.appendChild(useSvg("Art_Vector_Nose_TypeB")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`)); } } else if (slave.faceShape === "androgynous") { - r += jsInclude("Art_Vector_Eyes_TypeE"); - r += jsInclude("Art_Vector_Mouth_TypeE"); - r += jsInclude("Art_Vector_Nose_TypeA"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeE")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeE")); + res.appendChild(useSvg("Art_Vector_Nose_TypeA")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`)); } } else if (slave.faceShape === "cute") { - r += jsInclude("Art_Vector_Eyes_TypeC"); - r += jsInclude("Art_Vector_Mouth_TypeC"); - r += jsInclude("Art_Vector_Nose_TypeC"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeC")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeC")); + res.appendChild(useSvg("Art_Vector_Nose_TypeC")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeF_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeF_${eyebrowFullness}`)); } } else if (slave.faceShape === "sensual") { - r += jsInclude("Art_Vector_Eyes_TypeA"); - r += jsInclude("Art_Vector_Mouth_TypeA"); - r += jsInclude("Art_Vector_Nose_TypeE"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeA")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeA")); + res.appendChild(useSvg("Art_Vector_Nose_TypeE")); if (slave.eyebrowFullness === "pencil-thin") { - r += jsInclude("Art_Vector_Eyebrow_TypeC_Pencilthin"); + res.appendChild(useSvg("Art_Vector_Eyebrow_TypeC_Pencilthin")); } else if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeF_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeF_${eyebrowFullness}`)); } } else if (slave.faceShape === "exotic") { - r += jsInclude("Art_Vector_Eyes_TypeB"); - r += jsInclude("Art_Vector_Mouth_TypeC"); - r += jsInclude("Art_Vector_Nose_TypeF"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeB")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeC")); + res.appendChild(useSvg("Art_Vector_Nose_TypeF")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeA_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeA_${eyebrowFullness}`)); } } break; case "amerindian": case "latina": if (slave.faceShape === "normal") { - r += jsInclude("Art_Vector_Eyes_TypeB"); - r += jsInclude("Art_Vector_Mouth_TypeE"); - r += jsInclude("Art_Vector_Nose_TypeD"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeB")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeE")); + res.appendChild(useSvg("Art_Vector_Nose_TypeD")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeB_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeB_${eyebrowFullness}`)); } } else if (slave.faceShape === "masculine") { - r += jsInclude("Art_Vector_Eyes_TypeE"); - r += jsInclude("Art_Vector_Mouth_TypeD"); - r += jsInclude("Art_Vector_Nose_TypeF"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeE")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeD")); + res.appendChild(useSvg("Art_Vector_Nose_TypeF")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`)); } } else if (slave.faceShape === "androgynous") { - r += jsInclude("Art_Vector_Eyes_TypeA"); - r += jsInclude("Art_Vector_Mouth_TypeD"); - r += jsInclude("Art_Vector_Nose_TypeB"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeA")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeD")); + res.appendChild(useSvg("Art_Vector_Nose_TypeB")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeD_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeD_${eyebrowFullness}`)); } } else if (slave.faceShape === "cute") { - r += jsInclude("Art_Vector_Eyes_TypeF"); - r += jsInclude("Art_Vector_Mouth_TypeB"); - r += jsInclude("Art_Vector_Nose_TypeB"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeF")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeB")); + res.appendChild(useSvg("Art_Vector_Nose_TypeB")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeF_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeF_${eyebrowFullness}`)); } } else if (slave.faceShape === "sensual") { - r += jsInclude("Art_Vector_Eyes_TypeB"); - r += jsInclude("Art_Vector_Mouth_TypeE"); - r += jsInclude("Art_Vector_Nose_TypeC"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeB")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeE")); + res.appendChild(useSvg("Art_Vector_Nose_TypeC")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeF_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeF_${eyebrowFullness}`)); } } else if (slave.faceShape === "exotic") { - r += jsInclude("Art_Vector_Eyes_TypeC"); - r += jsInclude("Art_Vector_Mouth_TypeA"); - r += jsInclude("Art_Vector_Nose_TypeC"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeC")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeA")); + res.appendChild(useSvg("Art_Vector_Nose_TypeC")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeE_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeE_${eyebrowFullness}`)); } } break; case "black": if (slave.faceShape === "normal") { - r += jsInclude("Art_Vector_Eyes_TypeD"); - r += jsInclude("Art_Vector_Mouth_TypeB"); - r += jsInclude("Art_Vector_Nose_TypeF"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeD")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeB")); + res.appendChild(useSvg("Art_Vector_Nose_TypeF")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeF_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeF_${eyebrowFullness}`)); } } else if (slave.faceShape === "masculine") { - r += jsInclude("Art_Vector_Eyes_TypeA"); - r += jsInclude("Art_Vector_Mouth_TypeD"); - r += jsInclude("Art_Vector_Nose_TypeF"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeA")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeD")); + res.appendChild(useSvg("Art_Vector_Nose_TypeF")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeE_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeE_${eyebrowFullness}`)); } } else if (slave.faceShape === "androgynous") { - r += jsInclude("Art_Vector_Eyes_TypeF"); - r += jsInclude("Art_Vector_Mouth_TypeE"); - r += jsInclude("Art_Vector_Nose_TypeB"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeF")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeE")); + res.appendChild(useSvg("Art_Vector_Nose_TypeB")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeE_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeE_${eyebrowFullness}`)); } } else if (slave.faceShape === "cute") { - r += jsInclude("Art_Vector_Eyes_TypeC"); - r += jsInclude("Art_Vector_Mouth_TypeE"); - r += jsInclude("Art_Vector_Nose_TypeD"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeC")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeE")); + res.appendChild(useSvg("Art_Vector_Nose_TypeD")); if (slave.eyebrowFullness === "natural") { - r += jsInclude("Art_Vector_Eyebrow_TypeB_Natural"); + res.appendChild(useSvg("Art_Vector_Eyebrow_TypeB_Natural")); } else if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeD_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeD_${eyebrowFullness}`)); } } else if (slave.faceShape === "sensual") { - r += jsInclude("Art_Vector_Eyes_TypeC"); - r += jsInclude("Art_Vector_Mouth_TypeF"); - r += jsInclude("Art_Vector_Nose_TypeA"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeC")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeF")); + res.appendChild(useSvg("Art_Vector_Nose_TypeA")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`)); } } else if (slave.faceShape === "exotic") { - r += jsInclude("Art_Vector_Eyes_TypeE"); - r += jsInclude("Art_Vector_Mouth_TypeE"); - r += jsInclude("Art_Vector_Nose_TypeC"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeE")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeE")); + res.appendChild(useSvg("Art_Vector_Nose_TypeC")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeA_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeA_${eyebrowFullness}`)); } } break; case "middle eastern": if (slave.faceShape === "normal") { - r += jsInclude("Art_Vector_Eyes_TypeB"); - r += jsInclude("Art_Vector_Mouth_TypeA"); - r += jsInclude("Art_Vector_Nose_TypeA"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeB")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeA")); + res.appendChild(useSvg("Art_Vector_Nose_TypeA")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeA_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeA_${eyebrowFullness}`)); } } else if (slave.faceShape === "masculine") { - r += jsInclude("Art_Vector_Eyes_TypeD"); - r += jsInclude("Art_Vector_Mouth_TypeF"); - r += jsInclude("Art_Vector_Nose_TypeA"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeD")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeF")); + res.appendChild(useSvg("Art_Vector_Nose_TypeA")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeB_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeB_${eyebrowFullness}`)); } } else if (slave.faceShape === "androgynous") { - r += jsInclude("Art_Vector_Eyes_TypeF"); - r += jsInclude("Art_Vector_Mouth_TypeB"); - r += jsInclude("Art_Vector_Nose_TypeF"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeF")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeB")); + res.appendChild(useSvg("Art_Vector_Nose_TypeF")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeF_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeF_${eyebrowFullness}`)); } } else if (slave.faceShape === "cute") { - r += jsInclude("Art_Vector_Eyes_TypeB"); - r += jsInclude("Art_Vector_Mouth_TypeB"); - r += jsInclude("Art_Vector_Nose_TypeC"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeB")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeB")); + res.appendChild(useSvg("Art_Vector_Nose_TypeC")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeA_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeA_${eyebrowFullness}`)); } } else if (slave.faceShape === "sensual") { - r += jsInclude("Art_Vector_Eyes_TypeA"); - r += jsInclude("Art_Vector_Mouth_TypeD"); - r += jsInclude("Art_Vector_Nose_TypeA"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeA")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeD")); + res.appendChild(useSvg("Art_Vector_Nose_TypeA")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`)); } } else if (slave.faceShape === "exotic") { - r += jsInclude("Art_Vector_Eyes_TypeE"); - r += jsInclude("Art_Vector_Mouth_TypeE"); - r += jsInclude("Art_Vector_Nose_TypeE"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeE")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeE")); + res.appendChild(useSvg("Art_Vector_Nose_TypeE")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeE_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeE_${eyebrowFullness}`)); } } break; case "semitic": if (slave.faceShape === "normal") { - r += jsInclude("Art_Vector_Eyes_TypeB"); - r += jsInclude("Art_Vector_Mouth_TypeA"); - r += jsInclude("Art_Vector_Nose_TypeA"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeB")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeA")); + res.appendChild(useSvg("Art_Vector_Nose_TypeA")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeA_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeA_${eyebrowFullness}`)); } } else if (slave.faceShape === "masculine") { - r += jsInclude("Art_Vector_Eyes_TypeD"); - r += jsInclude("Art_Vector_Mouth_TypeF"); - r += jsInclude("Art_Vector_Nose_TypeA"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeD")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeF")); + res.appendChild(useSvg("Art_Vector_Nose_TypeA")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeB_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeB_${eyebrowFullness}`)); } } else if (slave.faceShape === "androgynous") { - r += jsInclude("Art_Vector_Eyes_TypeF"); - r += jsInclude("Art_Vector_Mouth_TypeB"); - r += jsInclude("Art_Vector_Nose_TypeF"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeF")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeB")); + res.appendChild(useSvg("Art_Vector_Nose_TypeF")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeF_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeF_${eyebrowFullness}`)); } } else if (slave.faceShape === "cute") { - r += jsInclude("Art_Vector_Eyes_TypeB"); - r += jsInclude("Art_Vector_Mouth_TypeB"); - r += jsInclude("Art_Vector_Nose_TypeC"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeB")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeB")); + res.appendChild(useSvg("Art_Vector_Nose_TypeC")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeA_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeA_${eyebrowFullness}`)); } } else if (slave.faceShape === "sensual") { - r += jsInclude("Art_Vector_Eyes_TypeA"); - r += jsInclude("Art_Vector_Mouth_TypeD"); - r += jsInclude("Art_Vector_Nose_TypeA"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeA")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeD")); + res.appendChild(useSvg("Art_Vector_Nose_TypeA")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`)); } } else if (slave.faceShape === "exotic") { - r += jsInclude("Art_Vector_Eyes_TypeE"); - r += jsInclude("Art_Vector_Mouth_TypeE"); - r += jsInclude("Art_Vector_Nose_TypeE"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeE")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeE")); + res.appendChild(useSvg("Art_Vector_Nose_TypeE")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeE_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeE_${eyebrowFullness}`)); } } break; case "indo-aryan": if (slave.faceShape === "normal") { - r += jsInclude("Art_Vector_Eyes_TypeE"); - r += jsInclude("Art_Vector_Mouth_TypeA"); - r += jsInclude("Art_Vector_Nose_TypeD"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeE")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeA")); + res.appendChild(useSvg("Art_Vector_Nose_TypeD")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeA_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeA_${eyebrowFullness}`)); } } else if (slave.faceShape === "masculine") { - r += jsInclude("Art_Vector_Eyes_TypeF"); - r += jsInclude("Art_Vector_Mouth_TypeD"); - r += jsInclude("Art_Vector_Nose_TypeE"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeF")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeD")); + res.appendChild(useSvg("Art_Vector_Nose_TypeE")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`)); } } else if (slave.faceShape === "androgynous") { - r += jsInclude("Art_Vector_Eyes_TypeC"); - r += jsInclude("Art_Vector_Mouth_TypeB"); - r += jsInclude("Art_Vector_Nose_TypeD"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeC")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeB")); + res.appendChild(useSvg("Art_Vector_Nose_TypeD")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeF_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeF_${eyebrowFullness}`)); } } else if (slave.faceShape === "cute") { - r += jsInclude("Art_Vector_Eyes_TypeC"); - r += jsInclude("Art_Vector_Mouth_TypeD"); - r += jsInclude("Art_Vector_Nose_TypeA"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeC")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeD")); + res.appendChild(useSvg("Art_Vector_Nose_TypeA")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeD_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeD_${eyebrowFullness}`)); } } else if (slave.faceShape === "sensual") { - r += jsInclude("Art_Vector_Eyes_TypeA"); - r += jsInclude("Art_Vector_Mouth_TypeE"); - r += jsInclude("Art_Vector_Nose_TypeC"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeA")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeE")); + res.appendChild(useSvg("Art_Vector_Nose_TypeC")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeD_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeD_${eyebrowFullness}`)); } } else if (slave.faceShape === "exotic") { - r += jsInclude("Art_Vector_Eyes_TypeA"); - r += jsInclude("Art_Vector_Mouth_TypeC"); - r += jsInclude("Art_Vector_Nose_TypeC"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeA")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeC")); + res.appendChild(useSvg("Art_Vector_Nose_TypeC")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`)); } } break; case "mixed race": if (slave.faceShape === "normal") { - r += jsInclude("Art_Vector_Eyes_TypeE"); - r += jsInclude("Art_Vector_Mouth_TypeA"); - r += jsInclude("Art_Vector_Nose_TypeD"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeE")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeA")); + res.appendChild(useSvg("Art_Vector_Nose_TypeD")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeA_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeA_${eyebrowFullness}`)); } } else if (slave.faceShape === "masculine") { - r += jsInclude("Art_Vector_Eyes_TypeF"); - r += jsInclude("Art_Vector_Mouth_TypeD"); - r += jsInclude("Art_Vector_Nose_TypeE"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeF")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeD")); + res.appendChild(useSvg("Art_Vector_Nose_TypeE")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`)); } } else if (slave.faceShape === "androgynous") { - r += jsInclude("Art_Vector_Eyes_TypeC"); - r += jsInclude("Art_Vector_Mouth_TypeB"); - r += jsInclude("Art_Vector_Nose_TypeD"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeC")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeB")); + res.appendChild(useSvg("Art_Vector_Nose_TypeD")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeF_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeF_${eyebrowFullness}`)); } } else if (slave.faceShape === "cute") { - r += jsInclude("Art_Vector_Eyes_TypeC"); - r += jsInclude("Art_Vector_Mouth_TypeD"); - r += jsInclude("Art_Vector_Nose_TypeA"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeC")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeD")); + res.appendChild(useSvg("Art_Vector_Nose_TypeA")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeD_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeD_${eyebrowFullness}`)); } } else if (slave.faceShape === "sensual") { - r += jsInclude("Art_Vector_Eyes_TypeA"); - r += jsInclude("Art_Vector_Mouth_TypeE"); - r += jsInclude("Art_Vector_Nose_TypeC"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeA")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeE")); + res.appendChild(useSvg("Art_Vector_Nose_TypeC")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeD_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeD_${eyebrowFullness}`)); } } else if (slave.faceShape === "exotic") { - r += jsInclude("Art_Vector_Eyes_TypeA"); - r += jsInclude("Art_Vector_Mouth_TypeC"); - r += jsInclude("Art_Vector_Nose_TypeC"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeA")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeC")); + res.appendChild(useSvg("Art_Vector_Nose_TypeC")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`)); } } break; default: if (slave.faceShape === "normal") { - r += jsInclude("Art_Vector_Eyes_TypeB"); - r += jsInclude("Art_Vector_Mouth_TypeA"); - r += jsInclude("Art_Vector_Nose_TypeA"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeB")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeA")); + res.appendChild(useSvg("Art_Vector_Nose_TypeA")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeA_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeA_${eyebrowFullness}`)); } } else if (slave.faceShape === "masculine") { - r += jsInclude("Art_Vector_Eyes_TypeD"); - r += jsInclude("Art_Vector_Mouth_TypeF"); - r += jsInclude("Art_Vector_Nose_TypeF"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeD")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeF")); + res.appendChild(useSvg("Art_Vector_Nose_TypeF")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeE_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeE_${eyebrowFullness}`)); } } else if (slave.faceShape === "androgynous") { - r += jsInclude("Art_Vector_Eyes_TypeE"); - r += jsInclude("Art_Vector_Mouth_TypeE"); - r += jsInclude("Art_Vector_Nose_TypeE"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeE")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeE")); + res.appendChild(useSvg("Art_Vector_Nose_TypeE")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeF_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeF_${eyebrowFullness}`)); } } else if (slave.faceShape === "cute") { - r += jsInclude("Art_Vector_Eyes_TypeB"); - r += jsInclude("Art_Vector_Mouth_TypeB"); - r += jsInclude("Art_Vector_Nose_TypeD"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeB")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeB")); + res.appendChild(useSvg("Art_Vector_Nose_TypeD")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeA_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeA_${eyebrowFullness}`)); } } else if (slave.faceShape === "sensual") { - r += jsInclude("Art_Vector_Eyes_TypeC"); - r += jsInclude("Art_Vector_Mouth_TypeC"); - r += jsInclude("Art_Vector_Nose_TypeC"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeC")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeC")); + res.appendChild(useSvg("Art_Vector_Nose_TypeC")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`)); } } else if (slave.faceShape === "exotic") { - r += jsInclude("Art_Vector_Eyes_TypeA"); - r += jsInclude("Art_Vector_Mouth_TypeC"); - r += jsInclude("Art_Vector_Nose_TypeC"); + res.appendChild(useSvg("Art_Vector_Eyes_TypeA")); + res.appendChild(useSvg("Art_Vector_Mouth_TypeC")); + res.appendChild(useSvg("Art_Vector_Nose_TypeC")); if (hasEyebrows === true) { - r += jsInclude(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`); + res.appendChild(useSvg(`Art_Vector_Eyebrow_TypeC_${eyebrowFullness}`)); } } } @@ -2388,39 +2428,39 @@ window.VectorArt = (function() { /* END FACIAL APPEARANCE */ if (slave.eyebrowPiercing === 1) { - r += jsInclude("Art_Vector_Eyebrow_Light"); + res.appendChild(useSvg("Art_Vector_Eyebrow_Light")); } else if (slave.eyebrowPiercing === 2) { - r += jsInclude("Art_Vector_Eyebrow_Heavy"); + res.appendChild(useSvg("Art_Vector_Eyebrow_Heavy")); } if (slave.nosePiercing === 1) { - r += jsInclude("Art_Vector_Nose_Light"); + res.appendChild(useSvg("Art_Vector_Nose_Light")); } else if (slave.nosePiercing === 2) { - r += jsInclude("Art_Vector_Nose_Heavy"); + res.appendChild(useSvg("Art_Vector_Nose_Heavy")); } if (slave.lipsPiercing === 1) { - r += jsInclude("Art_Vector_Lip_Light"); + res.appendChild(useSvg("Art_Vector_Lip_Light")); } else if (slave.lipsPiercing === 2) { - r += jsInclude("Art_Vector_Lip_Heavy"); + res.appendChild(useSvg("Art_Vector_Lip_Heavy")); } /* ADDONS */ if (slave.fuckdoll === 0) { /* Fuckdolls cannot be decorated */ if (slave.collar === "dildo gag") { - r += jsInclude("Art_Vector_Dildo_Gag"); + res.appendChild(useSvg("Art_Vector_Dildo_Gag")); } else if (slave.collar === "ball gag") { - r += jsInclude("Art_Vector_Ball_Gag"); + res.appendChild(useSvg("Art_Vector_Ball_Gag")); } else if (slave.collar === "bit gag") { - r += jsInclude("Art_Vector_Bit_Gag"); + res.appendChild(useSvg("Art_Vector_Bit_Gag")); } else if (slave.collar === "massive dildo gag") { - r += jsInclude("Art_Vector_Massive_Dildo_Gag"); + res.appendChild(useSvg("Art_Vector_Massive_Dildo_Gag")); } else if (slave.collar === "porcelain mask") { - r += jsInclude("Art_Vector_Porcelain_Mask"); + res.appendChild(useSvg("Art_Vector_Porcelain_Mask")); } if (slave.eyewear === "corrective glasses" || slave.eyewear === "glasses" || slave.eyewear === "blurring glasses") { - r += jsInclude("Art_Vector_Glasses"); + res.appendChild(useSvg("Art_Vector_Glasses")); } /* head clothing */ @@ -2447,15 +2487,15 @@ window.VectorArt = (function() { case "battlearmor": case "harem gauze": case "Western clothing": - r += jsInclude(`Art_Vector_Head_Outfit_${clothing2artSuffix(slave.clothes)}`); + res.appendChild(useSvg(`Art_Vector_Head_Outfit_${clothing2artSuffix(slave.clothes)}`)); break; case "a schutzstaffel uniform": case "a slutty schutzstaffel uniform": - r += jsInclude("Art_Vector_Head_Outfit_SchutzstaffelUniform"); + res.appendChild(useSvg("Art_Vector_Head_Outfit_SchutzstaffelUniform")); break; case "kitty lingerie": - r += jsInclude("Art_Vector_Cat_Ear_Fore"); - r += jsInclude("Art_Vector_Cat_Ear_Back"); + res.appendChild(useSvg("Art_Vector_Cat_Ear_Fore")); + res.appendChild(useSvg("Art_Vector_Cat_Ear_Back")); } } } @@ -2463,27 +2503,27 @@ window.VectorArt = (function() { function ArtVectorLeg() { /* Selection of matching SVG based on amputee level */ if (slave.amp === 0) { - r += jsInclude(`Art_Vector_Leg_${legSize}`); + res.appendChild(useSvg(`Art_Vector_Leg_${legSize}`)); if (slave.muscles >= 97) { - r += jsInclude(`Art_Vector_Leg_${legSize}_MHeavy`); + res.appendChild(useSvg(`Art_Vector_Leg_${legSize}_MHeavy`)); } else if (slave.muscles >= 62) { - r += jsInclude(`Art_Vector_Leg_${legSize}_MMedium`); + res.appendChild(useSvg(`Art_Vector_Leg_${legSize}_MMedium`)); } else if (slave.muscles >= 30) { - r += jsInclude(`Art_Vector_Leg_${legSize}_MLight`); + res.appendChild(useSvg(`Art_Vector_Leg_${legSize}_MLight`)); } } else if (slave.amp === 1) { - r += jsInclude("Art_Vector_Stump"); + res.appendChild(useSvg("Art_Vector_Stump")); } else if (slave.PLimb === 1 || slave.PLimb === 2) { /* slave is an amputee and has PLimbs equipped */ if (slave.amp === -1) { - r += jsInclude(`Art_Vector_Leg_ProstheticBasic_${legSize}`); + res.appendChild(useSvg(`Art_Vector_Leg_ProstheticBasic_${legSize}`)); } else if (slave.amp === -2) { - r += jsInclude(`Art_Vector_Leg_ProstheticSexy_${legSize}`); + res.appendChild(useSvg(`Art_Vector_Leg_ProstheticSexy_${legSize}`)); } else if (slave.amp === -3) { - r += jsInclude(`Art_Vector_Leg_ProstheticBeauty_${legSize}`); + res.appendChild(useSvg(`Art_Vector_Leg_ProstheticBeauty_${legSize}`)); } else if (slave.amp === -4) { - r += jsInclude(`Art_Vector_Leg_ProstheticCombat_${legSize}`); + res.appendChild(useSvg(`Art_Vector_Leg_ProstheticCombat_${legSize}`)); } else { /* slave.amp === -5 */ - r += jsInclude(`Art_Vector_Leg_ProstheticSwiss_${legSize}`); + res.appendChild(useSvg(`Art_Vector_Leg_ProstheticSwiss_${legSize}`)); } } } @@ -2498,16 +2538,16 @@ window.VectorArt = (function() { // eslint-disable-next-line camelcase T.art_pussy_tattoo_text = "Fucktoy"; } - r += jsInclude("Art_Vector_Pussy_Tattoo"); + res.appendChild(useSvg("Art_Vector_Pussy_Tattoo")); } if (slave.physicalAge < 11) { /* these art files exist, but draw empty svg's. Commented out for now to save on rendering time - r += jsInclude("Art_Vector_Pubic_Hair_None"); - r += jsInclude("Art_Vector_Pubic_Hair_Underarm_None"); + res.appendChild(useSvg("Art_Vector_Pubic_Hair_None")); + res.appendChild(useSvg("Art_Vector_Pubic_Hair_Underarm_None")); */ } else if (slave.physicalAge <= 13) { if (slave.pubicHStyle !== "waxed") { - r += jsInclude("Art_Vector_Pubic_Hair_Wispy"); + res.appendChild(useSvg("Art_Vector_Pubic_Hair_Wispy")); } } else if (slave.clothes !== "a comfortable bodysuit") { switch (slave.pubicHStyle) { @@ -2515,43 +2555,43 @@ window.VectorArt = (function() { case "hairless": case "waxed": /* commented out to save on rendering time - r += jsInclude("Art_Vector_Pubic_Hair_None"); + res.appendChild(useSvg("Art_Vector_Pubic_Hair_None")); */ break; case "strip": case "in a strip": if (torsoSize === "Obese" || torsoSize === "Fat") { - r += jsInclude("Art_Vector_Pubic_Hair_StripFat"); + res.appendChild(useSvg("Art_Vector_Pubic_Hair_StripFat")); } else { - r += jsInclude("Art_Vector_Pubic_Hair_Strip"); + res.appendChild(useSvg("Art_Vector_Pubic_Hair_Strip")); } break; case "neat": if (torsoSize === "Obese" || torsoSize === "Fat") { - r += jsInclude("Art_Vector_Pubic_Hair_NeatFat"); + res.appendChild(useSvg("Art_Vector_Pubic_Hair_NeatFat")); } else { - r += jsInclude("Art_Vector_Pubic_Hair_Neat"); + res.appendChild(useSvg("Art_Vector_Pubic_Hair_Neat")); } break; case "bushy in the front and neat in the rear": if (torsoSize === "Obese" || torsoSize === "Fat") { - r += jsInclude("Art_Vector_Pubic_Hair_BushFat"); + res.appendChild(useSvg("Art_Vector_Pubic_Hair_BushFat")); } else { - r += jsInclude("Art_Vector_Pubic_Hair_Bush"); + res.appendChild(useSvg("Art_Vector_Pubic_Hair_Bush")); } break; case "bushy": if (torsoSize === "Obese" || torsoSize === "Fat") { - r += jsInclude("Art_Vector_Pubic_Hair_BushyFat"); + res.appendChild(useSvg("Art_Vector_Pubic_Hair_BushyFat")); } else { - r += jsInclude("Art_Vector_Pubic_Hair_Bushy"); + res.appendChild(useSvg("Art_Vector_Pubic_Hair_Bushy")); } break; case "very bushy": if (torsoSize === "Obese" || torsoSize === "Fat") { - r += jsInclude("Art_Vector_Pubic_Hair_Very_BushyFat"); + res.appendChild(useSvg("Art_Vector_Pubic_Hair_Very_BushyFat")); } else { - r += jsInclude("Art_Vector_Pubic_Hair_Very_Bushy"); + res.appendChild(useSvg("Art_Vector_Pubic_Hair_Very_Bushy")); } } switch (slave.underArmHStyle) { @@ -2559,17 +2599,17 @@ window.VectorArt = (function() { case "waxed": case "bald": /* commented out to save on rendering time - r += jsInclude("Art_Vector_Pubic_Hair_Underarm_None"); + res.appendChild(useSvg("Art_Vector_Pubic_Hair_Underarm_None")); */ break; case "shaved": - r += jsInclude("Art_Vector_Pubic_Hair_Underarm_Shaved"); + res.appendChild(useSvg("Art_Vector_Pubic_Hair_Underarm_Shaved")); break; case "neat": - r += jsInclude("Art_Vector_Pubic_Hair_Underarm_Neat"); + res.appendChild(useSvg("Art_Vector_Pubic_Hair_Underarm_Neat")); break; case "bushy": - r += jsInclude("Art_Vector_Pubic_Hair_Underarm_Bushy"); + res.appendChild(useSvg("Art_Vector_Pubic_Hair_Underarm_Bushy")); } } } @@ -2577,7 +2617,7 @@ window.VectorArt = (function() { function ArtVectorPussy() { if (slave.vagina >= 0 && slave.clothes !== "a latex catsuit" && slave.clothes !== "a comfortable bodysuit" && slave.clothes !== "a cybersuit") { - r += jsInclude("Art_Vector_Pussy"); + res.appendChild(useSvg("Art_Vector_Pussy")); } } @@ -2611,29 +2651,29 @@ window.VectorArt = (function() { case "Western clothing": /* piercinglevel = 1, Light; piercinglevel = 2, Heavy; piercinglevel = 3, Smart; piercinglevel = 0, None */ if (slave.vaginaPiercing === 1) { - r += jsInclude("Art_Vector_Pussy_Piercing"); + res.appendChild(useSvg("Art_Vector_Pussy_Piercing")); } else if (slave.vaginaPiercing === 2) { - r += jsInclude("Art_Vector_Pussy_Piercing_Heavy"); + res.appendChild(useSvg("Art_Vector_Pussy_Piercing_Heavy")); } if (slave.clitPiercing === 1) { - r += jsInclude("Art_Vector_Clit_Piercing"); + res.appendChild(useSvg("Art_Vector_Clit_Piercing")); } else if (slave.clitPiercing === 2) { - r += jsInclude("Art_Vector_Clit_Piercing_Heavy"); + res.appendChild(useSvg("Art_Vector_Clit_Piercing_Heavy")); } else if (slave.clitPiercing === 3) { - r += jsInclude("Art_Vector_Clit_Piercing_Smart"); + res.appendChild(useSvg("Art_Vector_Clit_Piercing_Smart")); } } } function ArtVectorTorso() { - r += jsInclude(`Art_Vector_Torso_${torsoSize}`); + res.appendChild(useSvg(`Art_Vector_Torso_${torsoSize}`)); if (slave.muscles >= 97) { - r += jsInclude(`Art_Vector_Torso_${torsoSize}_MHeavy`); + res.appendChild(useSvg(`Art_Vector_Torso_${torsoSize}_MHeavy`)); } else if (slave.muscles >= 62) { - r += jsInclude(`Art_Vector_Torso_${torsoSize}_MMedium`); + res.appendChild(useSvg(`Art_Vector_Torso_${torsoSize}_MMedium`)); } else if (slave.muscles >= 30) { - r += jsInclude(`Art_Vector_Torso_${torsoSize}_MLight`); + res.appendChild(useSvg(`Art_Vector_Torso_${torsoSize}_MLight`)); } } @@ -2652,472 +2692,508 @@ window.VectorArt = (function() { break; /* no torso outfit */ /* manually handle special cases */ case "a cybersuit": - r += jsInclude(`Art_Vector_Torso_Outfit_Latex_${torsoSize}`); + res.appendChild(useSvg(`Art_Vector_Torso_Outfit_Latex_${torsoSize}`)); break; case "a slutty schutzstaffel uniform": - r += jsInclude(`Art_Vector_Torso_Outfit_SchutzstaffelUniform_${torsoSize}`); + res.appendChild(useSvg(`Art_Vector_Torso_Outfit_SchutzstaffelUniform_${torsoSize}`)); break; case "a niqab and abaya": case "a burqa": - r += jsInclude(`Art_Vector_Torso_Outfit_HijabAndAbaya_${torsoSize}`); + res.appendChild(useSvg(`Art_Vector_Torso_Outfit_HijabAndAbaya_${torsoSize}`)); break; default: - r += jsInclude(`Art_Vector_Torso_Outfit_${clothing2artSuffix(slave.clothes)}_${torsoSize}`); + res.appendChild(useSvg(`Art_Vector_Torso_Outfit_${clothing2artSuffix(slave.clothes)}_${torsoSize}`)); } if (V.seeVectorArtHighlights === 1) { if (wearingLatex === true) { if (slave.amp !== 0) { - r += jsInclude("Art_Vector_Torso_Outfit_Shine_Shoulder"); + res.appendChild(useSvg("Art_Vector_Torso_Outfit_Shine_Shoulder")); } if (slave.preg <= 0) { - r += jsInclude(`Art_Vector_Torso_Outfit_Shine_${torsoSize}`); + res.appendChild(useSvg(`Art_Vector_Torso_Outfit_Shine_${torsoSize}`)); } } } } return VectorArt; -})(); +}) (); -window.LegacyVectorArt = function(slave, artSize) { - const filePath = "'resources/vector"; + +App.Art.legacyVectorArtElement = function() { + const filePath = "resources/vector"; const skinFilePath = `${filePath}/body/white`; - const wearingLatex = slave.clothes === "a Fuckdoll suit" || slave.clothes === "restrictive latex" || slave.clothes === "a latex catsuit"; - let hairStyle, underArmHStyle, leftArmType, rightArmType, buttSize, legSize, shoesType, torsoSize, boobSize, ballSize, penisSize; - let needBoobs = true; - let r = jsInclude("SVG filters"); - - /* Set skin color */ - let skinFilter = `filter: url(#skin-${_.kebabCase(slave.skin)});`; - /* Set hair color */ - let hairFilter = `filter: url(#hair-${_.kebabCase(slave.hColor)});`; - let underArmFilter = `filter: url(#hair-${_.kebabCase(slave.underArmHColor)});`; - let pubesFilter = `filter: url(#hair-${_.kebabCase(slave.pubicHColor)});`; - - if (artSize === 1) { - r += `<img class='paperdoll' src=${filePath}/test ui.svg'/`; - } - if (slave.custom.hairVector) { - hairStyle = slave.custom.hairVector; - } else { - hairStyle = (["afro", "braided", "bun", "buzzcut", "dreadlocks", "eary", "luxurious", "messy", "neat", "ponytail", "strip", "tails", "trimmed", "up"].includes(slave.hStyle) ? slave.hStyle : "neat"); - } + /** + * @param {App.Entity.SlaveState} slave + * @param {number} artSize + * @returns {DocumentFragment} + */ + function render(slave, artSize) { + const wearingLatex = slave.clothes === "a Fuckdoll suit" || slave.clothes === "restrictive latex" || slave.clothes === "a latex catsuit"; + let hairStyle, underArmHStyle, leftArmType, rightArmType, buttSize, legSize, shoesType, torsoSize, boobSize, ballSize, penisSize; + let needBoobs = true; - underArmHStyle = slave.underArmHStyle; - - /* Shoulder width and arm or no arm */ - if (slave.amp !== 1) { - if (slave.devotion > 50) { - leftArmType = "high"; - rightArmType = "high"; - } else if (slave.trust >= -20) { - if (slave.devotion < -20) { - leftArmType = "rebel"; - rightArmType = "low"; - } else if (slave.devotion <= 20) { - leftArmType = "low"; - rightArmType = "low"; - } else { - leftArmType = "mid"; - rightArmType = "high"; - } - } else { - leftArmType = "mid"; - rightArmType = "mid"; + const res = document.createDocumentFragment(); + res.appendChild(App.Utils.htmlToElement(App.Utils.passageElement("SVG filters").textContent)); + + /* Set skin color */ + let skinFilter = `filter: url(#skin-${_.kebabCase(slave.skin)});`; + /* Set hair color */ + let hairFilter = `filter: url(#hair-${_.kebabCase(slave.hColor)});`; + let underArmFilter = `filter: url(#hair-${_.kebabCase(slave.underArmHColor)});`; + let pubesFilter = `filter: url(#hair-${_.kebabCase(slave.pubicHColor)});`; + + if (artSize === 1) { + addImg(res, "test ui"); } - if (wearingLatex === false) { - r += `<img class='paperdoll' src=${skinFilePath}/arm right ${rightArmType}.svg' style='${skinFilter}'>`; - if (slave.underArmHStyle === "bushy") { - r += `<img class='paperdoll' src=${filePath}/hair/underArm ${underArmHStyle} right.svg' style='{underArmFilter}'/>`; - } + if (slave.custom.hairVector) { + hairStyle = slave.custom.hairVector; } else { - if (slave.fuckdoll !== 0) { - rightArmType = "mid"; - } - r += `<img class='paperdoll' src=${filePath}/outfit/arm right ${rightArmType} latex.svg'/>`; + hairStyle = (["afro", "braided", "bun", "buzzcut", "dreadlocks", "eary", "luxurious", "messy", "neat", "ponytail", "strip", "tails", "trimmed", "up"].includes(slave.hStyle) ? slave.hStyle : "neat"); } - } else if (wearingLatex === false && slave.underArmHStyle === "bushy") { - r += `<img class='paperdoll' src=${filePath}/hair/underArm ${underArmHStyle} right.svg' style='{underArmFilter}'/>`; - } - /* Hair Aft */ - if (slave.fuckdoll === 0) { - switch (slave.hStyle) { - case "eary": - case "luxurious": - case "messy": - case "neat": - case "tails": - case "trimmed": - r += `<img class='paperdoll' src=${filePath}/hair/${hairStyle} back.svg' style='${hairFilter}'/>`; - } - } + underArmHStyle = slave.underArmHStyle; - /* Tailed Plug */ - if (slave.buttplugAttachment === "tail") { - r += `<img class='paperdoll' src=${filePath}/outfit/tail plug.svg' style='${hairFilter}'/>`; - } + /* Shoulder width and arm or no arm */ + if (slave.amp !== 1) { + if (slave.devotion > 50) { + leftArmType = "high"; + rightArmType = "high"; + } else if (slave.trust >= -20) { + if (slave.devotion < -20) { + leftArmType = "rebel"; + rightArmType = "low"; + } else if (slave.devotion <= 20) { + leftArmType = "low"; + rightArmType = "low"; + } else { + leftArmType = "mid"; + rightArmType = "high"; + } + } else { + leftArmType = "mid"; + rightArmType = "mid"; + } - /* Butt */ - if (slave.amp !== 1) { - if (slave.butt > 6) { - buttSize = 3; - } else if (slave.butt > 4) { - buttSize = 2; - } else if (slave.butt > 2) { - buttSize = 1; - } else { - buttSize = 0; + if (wearingLatex === false) { + addSkinImg(res, `arm right ${rightArmType}`, skinFilter); + if (slave.underArmHStyle === "bushy") { + addImg(res, `hair/underArm ${underArmHStyle} right`, underArmFilter); + } + } else { + if (slave.fuckdoll !== 0) { + rightArmType = "mid"; + } + addImg(res, `outfit/arm right ${rightArmType} latex`); + } + } else if (wearingLatex === false && slave.underArmHStyle === "bushy") { + addImg(res, `hair/underArm ${underArmHStyle} right`, underArmFilter); } - if (wearingLatex === true) { - r += `<img class='paperdoll' src=${filePath}/outfit/butt ${buttSize} latex.svg' style='${skinFilter}'>`; - } else { - r += `<img class='paperdoll' src=${skinFilePath}/butt ${buttSize}.svg' style='${skinFilter}'>`; + /* Hair Aft */ + if (slave.fuckdoll === 0) { + switch (slave.hStyle) { + case "eary": + case "luxurious": + case "messy": + case "neat": + case "tails": + case "trimmed": + addImg(res, `hair/${hairStyle} back`, hairFilter); + } } - } - /* Leg + 1 size up when chubby or fat */ - if (slave.hips < 0) { - if (slave.weight > 95) { /* Chubby */ - legSize = "normal"; - } else { - legSize = "narrow"; - } - } else if (slave.hips === 0) { - if (slave.weight > 95) { /* Chubby */ - legSize = "wide"; - } else { - legSize = "normal"; + /* Tailed Plug */ + if (slave.buttplugAttachment === "tail") { + addImg(res, "outfit/tail plug", hairFilter); } - } else { - legSize = "wide"; - } - if (slave.amp === 1) { - legSize = `stump ${legSize}`; - } - if (wearingLatex === true && slave.amp !== 1) { - r += `<img class='paperdoll' src=${filePath}/outfit/leg ${legSize} latex.svg'/>`; - } else { - r += `<img class='paperdoll' src=${skinFilePath}/leg ${legSize}.svg' style='${skinFilter}'>`; - } + /* Butt */ + if (slave.amp !== 1) { + if (slave.butt > 6) { + buttSize = 3; + } else if (slave.butt > 4) { + buttSize = 2; + } else if (slave.butt > 2) { + buttSize = 1; + } else { + buttSize = 0; + } - /* Feet */ - if (slave.amp !== 1) { - if (slave.shoes === "heels") { - shoesType = "heel"; - } else if (slave.shoes === "extreme heels") { + if (wearingLatex === true) { + addImg(res, `outfit/butt ${buttSize} latex`, skinFilter); + } else { + addSkinImg(res, `butt ${buttSize}`, skinFilter); + } + } + + /* Leg + 1 size up when chubby or fat */ + if (slave.hips < 0) { if (slave.weight > 95) { /* Chubby */ - shoesType = "extreme heel wide"; + legSize = "normal"; } else { - shoesType = "extreme heel"; + legSize = "narrow"; } - } else if (slave.shoes === "boots") { + } else if (slave.hips === 0) { if (slave.weight > 95) { /* Chubby */ - shoesType = "boot wide"; + legSize = "wide"; } else { - shoesType = "boot"; + legSize = "normal"; } - } else if (slave.shoes === "flats") { - shoesType = "flat"; } else { - r += `<img class='paperdoll' src=${skinFilePath}/feet.svg' style='${skinFilter}'>`; + legSize = "wide"; } - if (slave.shoes === "extreme heels" || slave.shoes === "boots") { - if (wearingLatex === true) { - r += `<img class='paperdoll' src=${filePath}/outfit/${shoesType} latex.svg'/>`; + if (slave.amp === 1) { + legSize = `stump ${legSize}`; + } + + if (wearingLatex === true && slave.amp !== 1) { + addImg(res, `outfit/leg ${legSize} latex`); + } else { + addSkinImg(res, `leg ${legSize}`, skinFilter); + } + + /* Feet */ + if (slave.amp !== 1) { + if (slave.shoes === "heels") { + shoesType = "heel"; + } else if (slave.shoes === "extreme heels") { + if (slave.weight > 95) { /* Chubby */ + shoesType = "extreme heel wide"; + } else { + shoesType = "extreme heel"; + } + } else if (slave.shoes === "boots") { + if (slave.weight > 95) { /* Chubby */ + shoesType = "boot wide"; + } else { + shoesType = "boot"; + } + } else if (slave.shoes === "flats") { + shoesType = "flat"; } else { - r += `<img class='paperdoll' src=${filePath}/outfit/${shoesType}.svg'/>`; + addSkinImg(res, "feet", skinFilter); } - } else if (slave.shoes === "heels" || slave.shoes === "flats") { - if (wearingLatex === true) { - r += `<img class='paperdoll' src=${filePath}/outfit/${shoesType} latex.svg'/>`; - } else { - r += `<img class='paperdoll' src=${skinFilePath}/${shoesType}.svg' style='${skinFilter}'>`; + if (slave.shoes === "extreme heels" || slave.shoes === "boots") { + addImg(res, `outfit/${shoesType}${wearingLatex ? " latex": ""}`); + } else if (slave.shoes === "heels" || slave.shoes === "flats") { + if (wearingLatex === true) { + addImg(res, `outfit/${shoesType} latex`); + } else { + addSkinImg(res, `${shoesType}`, skinFilter); + } } } - } - /* Torso */ - if (slave.waist < -40) { - if (slave.weight > 30) { - torsoSize = "hourglass"; + /* Torso */ + if (slave.waist < -40) { + if (slave.weight > 30) { + torsoSize = "hourglass"; + } else { + torsoSize = "unnatural"; + } + } else if (slave.waist <= 10) { + if (slave.weight > 30) { + torsoSize = "normal"; + } else { + torsoSize = "hourglass"; + } } else { - torsoSize = "unnatural"; - } - } else if (slave.waist <= 10) { - if (slave.weight > 30) { torsoSize = "normal"; - } else { - torsoSize = "hourglass"; } - } else { - torsoSize = "normal"; - } - r += `<img class='paperdoll' src=${skinFilePath}/torso ${torsoSize}.svg' style='${skinFilter}'>`; - if (wearingLatex === true) { - r += `<img class='paperdoll' src=${filePath}/outfit/torso ${torsoSize} latex.svg'/>`; - } else if (slave.clothes === "uncomfortable straps") { - r += `<img class='paperdoll' src=${filePath}/outfit/torso ${torsoSize} straps.svg'/>`; - } + addSkinImg(res, `torso ${torsoSize}`, skinFilter); + if (wearingLatex === true) { + addImg(res, `outfit/torso ${torsoSize} latex`); + } else if (slave.clothes === "uncomfortable straps") { + addImg(res, `outfit/torso ${torsoSize} straps`); + } - if (slave.amp !== 1) { - if (wearingLatex === false) { - if (leftArmType === "high") { - r += `<img class='paperdoll' src=${skinFilePath}/arm left ${leftArmType}.svg' style='${skinFilter}'>`; - if (slave.underArmHStyle === "bushy") { - r += `<img class='paperdoll' src=${filePath}/hair/underArm ${underArmHStyle} left.svg' style='${underArmFilter}'/>`; + if (slave.amp !== 1) { + if (wearingLatex === false) { + if (leftArmType === "high") { + addSkinImg(res, `arm left ${leftArmType}`, skinFilter); + if (slave.underArmHStyle === "bushy") { + addImg(res, `hair/underArm ${underArmHStyle} left`, underArmFilter); + } + } else { + if (slave.underArmHStyle === "bushy") { + addImg(res, `hair/underArm ${underArmHStyle} left`, underArmFilter); + } + addSkinImg(res, `arm left ${leftArmType}`, skinFilter); } + addSkinImg(res, `arm left ${leftArmType}`, skinFilter); } else { - if (slave.underArmHStyle === "bushy") { - r += `<img class='paperdoll' src=${filePath}/hair/underArm ${underArmHStyle} left.svg' style='${underArmFilter}'/>`; + if (slave.fuckdoll !== 0) { + leftArmType = "mid"; } - r += `<img class='paperdoll' src=${skinFilePath}/arm left ${leftArmType}.svg' style='${skinFilter}'>`; + addImg(res, `outfit/arm left ${leftArmType} latex`); } - r += `<img class='paperdoll' src=${skinFilePath}/arm left ${leftArmType}.svg' style='${skinFilter}'>`; - } else { - if (slave.fuckdoll !== 0) { - leftArmType = "mid"; - } - r += `<img class='paperdoll' src=${filePath}/outfit/arm left ${leftArmType} latex.svg'/>`; + } else if (wearingLatex === false && slave.underArmHStyle === "bushy") { + addImg(res, `hair/underArm ${underArmHStyle} left`, underArmFilter); } - } else if (wearingLatex === false && slave.underArmHStyle === "bushy") { - r += `<img class='paperdoll' src=${filePath}/hair/underArm ${underArmHStyle} left.svg' style='${underArmFilter}'/>`; - } - /* Vagina */ - if (slave.vagina >= 0) { - r += `<img class='paperdoll' src=${skinFilePath}/vagina.svg' style='${skinFilter}'>`; - if (slave.clitPiercing === 1) { - r += `<img class='paperdoll' src=${filePath}/body/addon/clit piercing.svg'/>`; - } else if (slave.clitPiercing === 2) { - r += `<img class='paperdoll' src=${filePath}/body/addon/clit piercing heavy.svg'/>`; - } else if (slave.clitPiercing === 3) { - r += `<img class='paperdoll' src=${filePath}/body/addon/clit piercing smart.svg'/>`; - } + /* Vagina */ + if (slave.vagina >= 0) { + addSkinImg(res, "vagina", skinFilter); + if (slave.clitPiercing === 1) { + addImg(res, "body/addon/clit piercing"); + } else if (slave.clitPiercing === 2) { + addImg(res, "body/addon/clit piercing heavy"); + } else if (slave.clitPiercing === 3) { + addImg(res, "body/addon/clit piercing smart"); + } - if (slave.vaginaPiercing === 1) { - r += `<img class='paperdoll' src=${filePath}/body/addon/pussy piercing.svg'/>`; - } else if (slave.vaginaPiercing === 2) { - r += `<img class='paperdoll' src=${filePath}/body/addon/pussy piercing heavy.svg'/>`; + if (slave.vaginaPiercing === 1) { + addImg(res, "body/addon/pussy piercing"); + } else if (slave.vaginaPiercing === 2) { + addImg(res, "body/addon/pussy piercing heavy"); + } } - } - - /* Collar */ - switch (slave.collar) { - case "nice retirement counter": - case "cruel retirement counter": - case "leather with cowbell": - case "pretty jewelry": - case "heavy gold": - case "satin choker": - case "stylish leather": - case "neck corset": - case "shock punishment": - case "tight steel": - case "uncomfortable leather": - case "dildo gag": - r += `<img class='paperdoll' src=${filePath}/outfit/${slave.collar}.svg'/>`; - } - /* Head base image */ - if (wearingLatex === true) { - r += `<img class='paperdoll' src=${filePath}/outfit/head latex.svg'/>`; - } else { - r += `<img class='paperdoll' src=${skinFilePath}/head.svg' style='${skinFilter}'>`; - } - - /* Glasses */ - if (slave.eyewear === "corrective glasses" || slave.eyewear === "glasses" || slave.eyewear === "blurring glasses") { - r += `<img class='paperdoll' src=${filePath}/outfit/glasses.svg'/>`; - } - - /* Chastity belt or Pubic hair */ - if (slave.chastityPenis === 1 || slave.chastityVagina === 1 || slave.chastityAnus === 1) { - if (slave.chastityPenis === 1) { - r += `<img class='paperdoll' src=${filePath}/outfit/chastity male aft.svg'/>`; - } - if (slave.chastityVagina === 1) { - r += `<img class='paperdoll' src=${filePath}/outfit/chastity female.svg'/>`; + /* Collar */ + switch (slave.collar) { + case "nice retirement counter": + case "cruel retirement counter": + case "leather with cowbell": + case "pretty jewelry": + case "heavy gold": + case "satin choker": + case "stylish leather": + case "neck corset": + case "shock punishment": + case "tight steel": + case "uncomfortable leather": + case "dildo gag": + addImg(res, `outfit/${slave.collar}`); } - r += `<img class='paperdoll' src=${filePath}/outfit/chastity base.svg'/>`; - } else if (slave.pubicHStyle !== "waxed" && slave.pubicHStyle !== "bald" && slave.pubicHStyle !== "hairless") { - let pubicHStyle = (slave.pubicHStyle === "in a strip" ? "strip" : slave.pubicHStyle); - r += `<img class='paperdoll' src=${filePath}/hair/pubes ${pubicHStyle}.svg' style='${pubesFilter}'/>`; - } - /* if pregnant or has a belly */ - if (slave.belly >= 5000) { - r += `<img class='paperdoll' src=${skinFilePath}/preg belly 5000.svg' style='${skinFilter}'>`; - if (slave.navelPiercing >= 1) { /* Navel Piercing*/ - r += `<img class='paperdoll' src=${filePath}/body/addon/preg navel piercing.svg'/>`; - } - if (slave.navelPiercing === 2) { - r += `<img class='paperdoll' src=${filePath}/body/addon/preg navel piercing heavy.svg'/>`; - } - } else if (slave.belly <= -100) { /* condition is currently reversed until the vector can be fixed */ - r += `<img class='paperdoll' src=${skinFilePath}/preg belly 100.svg' style='${skinFilter}'>`; - /* - if (slave.navelPiercing >= 1)/Navel Piercing/ - r += `<img class='paperdoll' src=${filePath}/body/addon/preg navel piercing.svg'/>`; - if (slave.navelPiercing === 2) - r += `<img class='paperdoll' src=${filePath}/body/addon/preg navel piercing heavy.svg'/>`; - */ - } else { - if (slave.navelPiercing >= 1) { /* Navel Piercing*/ - r += `<img class='paperdoll' src=${filePath}/body/addon/navel piercing.svg'/>`; + /* Head base image */ + if (wearingLatex === true) { + addImg(res, "outfit/head latex"); + } else { + addSkinImg(res, "head", skinFilter); } - if (slave.navelPiercing === 2) { - r += `<img class='paperdoll' src=${filePath}/body/addon/navel piercing heavy.svg'/>`; + + /* Glasses */ + if (slave.eyewear === "corrective glasses" || slave.eyewear === "glasses" || slave.eyewear === "blurring glasses") { + addImg(res, "outfit/glasses"); } - } - /* Boob */ - if (slave.boobs < 300) { - boobSize = 0; - } else if (slave.boobs < 500) { - boobSize = 1; - } else if (slave.boobs < 800) { - boobSize = 2; - } else if (slave.boobs < 1600) { - boobSize = 3; - } else if (slave.boobs < 3200) { - boobSize = 4; - } else if (slave.boobs < 6400) { - boobSize = 5; - } else if (slave.boobs < 12000) { - boobSize = 6; - } else { - boobSize = 7; - } + /* Chastity belt or Pubic hair */ + if (slave.chastityPenis === 1 || slave.chastityVagina === 1 || slave.chastityAnus === 1) { + if (slave.chastityPenis === 1) { + addImg(res, "outfit/chastity male aft"); + } + if (slave.chastityVagina === 1) { + addImg(res, "outfit/chastity female"); + } + addImg(res, "outfit/chastity base"); + } else if (slave.pubicHStyle !== "waxed" && slave.pubicHStyle !== "bald" && slave.pubicHStyle !== "hairless") { + let pubicHStyle = (slave.pubicHStyle === "in a strip" ? "strip" : slave.pubicHStyle); + addImg(res, `hair/pubes ${pubicHStyle}`, pubesFilter); + } - /* Scrotum */ - if (slave.scrotum > 0) { - if (slave.scrotum >= 6) { - ballSize = 4; - } else if (slave.scrotum >= 4) { - ballSize = 3; - } else if (slave.scrotum >= 3) { - ballSize = 2; - } else if (slave.scrotum >= 2) { - ballSize = 1; + /* if pregnant or has a belly */ + if (slave.belly >= 5000) { + addSkinImg(res, "preg belly 5000", skinFilter); + if (slave.navelPiercing >= 1) { /* Navel Piercing*/ + addImg(res, "body/addon/preg navel piercing"); + } + if (slave.navelPiercing === 2) { + addImg(res, "body/addon/preg navel piercing heavy"); + } + } else if (slave.belly <= -100) { /* condition is currently reversed until the vector can be fixed */ + addSkinImg(res, "preg belly 100", skinFilter); + /* + if (slave.navelPiercing >= 1)/Navel Piercing/ + r += `<img class='paperdoll' src=${filePath}/body/addon/preg navel piercing.svg'/>`; + if (slave.navelPiercing === 2) + r += `<img class='paperdoll' src=${filePath}/body/addon/preg navel piercing heavy.svg'/>`; + */ } else { - ballSize = 0; + if (slave.navelPiercing >= 1) { /* Navel Piercing*/ + addImg(res, "body/addon/navel piercing"); + } + if (slave.navelPiercing === 2) { + addImg(res, "body/addon/navel piercing heavy"); + } } - } - /* Penis */ - if (slave.dick > 0) { - if (slave.dick >= 8) { - penisSize = 6; - } else if (slave.dick >= 7) { - penisSize = 5; - } else if (slave.dick >= 6) { - penisSize = 4; - } else if (slave.dick >= 5) { - penisSize = 3; - } else if (slave.dick >= 4) { - penisSize = 2; - } else if (slave.dick >= 2) { - penisSize = 1; + /* Boob */ + if (slave.boobs < 300) { + boobSize = 0; + } else if (slave.boobs < 500) { + boobSize = 1; + } else if (slave.boobs < 800) { + boobSize = 2; + } else if (slave.boobs < 1600) { + boobSize = 3; + } else if (slave.boobs < 3200) { + boobSize = 4; + } else if (slave.boobs < 6400) { + boobSize = 5; + } else if (slave.boobs < 12000) { + boobSize = 6; } else { - penisSize = 0; + boobSize = 7; + } + + /* Scrotum */ + if (slave.scrotum > 0) { + if (slave.scrotum >= 6) { + ballSize = 4; + } else if (slave.scrotum >= 4) { + ballSize = 3; + } else if (slave.scrotum >= 3) { + ballSize = 2; + } else if (slave.scrotum >= 2) { + ballSize = 1; + } else { + ballSize = 0; + } } - } - - /* Boob */ - if (slave.dick > 0) { - if (canAchieveErection(slave)) { - if (boobSize < 6) { - if (wearingLatex === true) { - /* normal case: outfit hides boobs */ - r += `<img class='paperdoll' src=${filePath}/outfit/boob ${boobSize} latex.svg'/>`; - if (slave.lactation > 0) { - r += `<img class='paperdoll' src=${skinFilePath}/boob ${boobSize} areola.svg' style='${skinFilter}'>`; - } - } else { - r += `<img class='paperdoll' src=${skinFilePath}/boob ${boobSize}.svg' style='${skinFilter}'>`; - r += `<img class='paperdoll' src=${skinFilePath}/boob ${boobSize} areola.svg' style='${skinFilter}'>`; - } - /* special case: straps are actually dawn over the boobs */ - if (slave.clothes === "uncomfortable straps") { - r += `<img class='paperdoll' src=${filePath}/outfit/boob ${boobSize} straps.svg'/>`; - } - needBoobs = false; + /* Penis */ + if (slave.dick > 0) { + if (slave.dick >= 8) { + penisSize = 6; + } else if (slave.dick >= 7) { + penisSize = 5; + } else if (slave.dick >= 6) { + penisSize = 4; + } else if (slave.dick >= 5) { + penisSize = 3; + } else if (slave.dick >= 4) { + penisSize = 2; + } else if (slave.dick >= 2) { + penisSize = 1; + } else { + penisSize = 0; } } - } - if (slave.vagina > 0) { + + /* Boob */ if (slave.dick > 0) { - r += '<div class="highPenis">'; - if (slave.scrotum > 0) { - r += `<img class='paperdoll' src=${skinFilePath}/ball ${ballSize}.svg' style='${skinFilter}'>`; - } if (canAchieveErection(slave)) { - r += `<img class='paperdoll' src=${skinFilePath}/penis ${penisSize}.svg' style='${skinFilter}'>`; - } else { - r += `<img class='paperdoll' src=${skinFilePath}/flaccid ${penisSize}.svg' style='${skinFilter}'>`; - if (slave.chastityPenis === 1) { - r += `<img class='paperdoll' src=${filePath}/outfit/chastity male fore ${penisSize}.svg'/>`; + if (boobSize < 6) { + if (wearingLatex === true) { + /* normal case: outfit hides boobs */ + addImg(res, `outfit/boob ${boobSize} latex`); + if (slave.lactation > 0) { + addSkinImg(res, `boob ${boobSize} areola`, skinFilter); + } + } else { + addSkinImg(res, `boob ${boobSize}`, skinFilter); + addSkinImg(res, `boob ${boobSize} areola`, skinFilter); + } + /* special case: straps are actually dawn over the boobs */ + if (slave.clothes === "uncomfortable straps") { + addImg(res, `outfit/boob ${boobSize} straps`); + } + + needBoobs = false; } } - r += '</div>'; } - } else { - if (slave.dick > 0) { - r += '<div class="lowPenis">'; - if (slave.scrotum > 0) { - r += `<img class='paperdoll' src=${skinFilePath}/ball ${ballSize}.svg' style='${skinFilter}'>`; + if (slave.vagina > 0) { + if (slave.dick > 0) { + const divPenis = document.createElement("div"); + divPenis.className = "highPenis"; + res.appendChild(divPenis); + if (slave.scrotum > 0) { + addSkinImg(divPenis, `ball ${ballSize}`, skinFilter); + } + if (canAchieveErection(slave)) { + addSkinImg(divPenis, `penis ${penisSize}`, skinFilter); + } else { + addSkinImg(divPenis, `flaccid ${penisSize}`, skinFilter); + if (slave.chastityPenis === 1) { + addImg(divPenis, `outfit/chastity male fore ${penisSize}`); + } + } } - if (canAchieveErection(slave)) { - r += `<img class='paperdoll' src=${skinFilePath}/penis ${penisSize}.svg' style='${skinFilter}'>`; - } else { - r += `<img class='paperdoll' src=${skinFilePath}/flaccid ${penisSize}.svg' style='${skinFilter}'>`; - if (slave.chastityPenis === 1) { - r += `<img class='paperdoll' src=${filePath}/outfit/chastity male fore ${penisSize}.svg'/>`; + } else { + if (slave.dick > 0) { + const divPenis = document.createElement("div"); + divPenis.className = "lowPenis"; + res.appendChild(divPenis); + if (slave.scrotum > 0) { + addSkinImg(divPenis, `ball ${ballSize}`, skinFilter); + } + if (canAchieveErection(slave)) { + addSkinImg(divPenis, `penis ${penisSize}`, skinFilter); + } else { + addSkinImg(divPenis, `flaccid ${penisSize}`, skinFilter); + if (slave.chastityPenis === 1) { + addImg(divPenis, `outfit/chastity male fore ${penisSize}`); + } } } - r += '</div>'; } - } - if (needBoobs === true) { - if (wearingLatex === true) { - r += `<img class='paperdoll' src=${filePath}/outfit/boob ${boobSize} latex.svg'/>`; - if (slave.lactation > 0) { - r += `<img class='paperdoll' src=${skinFilePath}/boob ${boobSize} areola.svg' style='${skinFilter}'>`; + if (needBoobs === true) { + if (wearingLatex === true) { + addImg(res, `outfit/boob ${boobSize} latex`); + if (slave.lactation > 0) { + addSkinImg(res, `boob ${boobSize} areola`, skinFilter); + } + } else { + addSkinImg(res, `boob ${boobSize}`, skinFilter); + addSkinImg(res, `boob ${boobSize} areola`, skinFilter); + } + /* special case: straps are actually dawn over the boobs */ + if (slave.clothes === "uncomfortable straps") { + addImg(res, `outfit/boob ${boobSize} straps`); } - } else { - r += `<img class='paperdoll' src=${skinFilePath}/boob ${boobSize}.svg' style='${skinFilter}'>`; - r += `<img class='paperdoll' src=${skinFilePath}/boob ${boobSize} areola.svg' style='${skinFilter}'>`; } - /* special case: straps are actually dawn over the boobs */ - if (slave.clothes === "uncomfortable straps") { - r += `<img class='paperdoll' src=${filePath}/outfit/boob ${boobSize} straps.svg'/>`; + + /* piercings */ + if (slave.nipplesPiercing === 1) { + addImg(res, `body/addon/boob ${boobSize} piercing`); + } else if (slave.nipplesPiercing === 2) { + addImg(res, `body/addon/boob ${boobSize} piercing heavy`); } - } - /* piercings */ - if (slave.nipplesPiercing === 1) { - r += `<img class='paperdoll' src=${filePath}/body/addon/boob ${boobSize} piercing.svg'/>`; - } else if (slave.nipplesPiercing === 2) { - r += `<img class='paperdoll' src=${filePath}/body/addon/boob ${boobSize} piercing heavy.svg'/>`; - } + if (slave.areolaePiercing === 1) { + addImg(res, `body/addon/boob ${boobSize} areola piercing`); + } + + /* clavicle */ + addImg(res, "body/addon/clavicle"); + + /* Hair Foreground */ + if (slave.hStyle !== "shaved" && slave.fuckdoll === 0) { + addImg(res, `/hair/${hairStyle} front`, hairFilter); + } - if (slave.areolaePiercing === 1) { - r += `<img class='paperdoll' src=${filePath}/body/addon/boob ${boobSize} areola piercing.svg'/>`; + return res; } - /* clavicle */ - r += `<img class='paperdoll' src=${filePath}/body/addon/clavicle.svg'/>`; + /** + * @param {Node} container + * @param {string} artFile + * @param {string} [style] + */ + function addImg(container, artFile, style) { + const res = document.createElement("img"); + res.setAttribute("class", "paperdoll"); + res.setAttribute("src", `${filePath}/${artFile}.svg`); + if (style !== undefined) { + res.setAttribute("style", style); + } + container.appendChild(res); + return res; + } - /* Hair Foreground */ - if (slave.hStyle !== "shaved" && slave.fuckdoll === 0) { - r += `<img class='paperdoll' src=${filePath}/hair/${hairStyle} front.svg' style='${hairFilter}'/>`; + /** + * @param {Node} container + * @param {string} artFile + * @param {string} [style] + */ + function addSkinImg(container, artFile, style) { + return addImg(container, 'body/white/' + artFile, style); } - return r; -}; + return render; +}(); diff --git a/src/art/vector_revamp/vectorRevampedArtControl.js b/src/art/vector_revamp/vectorRevampedArtControl.js index 6c4c727da020657212c1315b56f6c3e214d4dd19..1786cd21cdfb5bb364a92734b259f18dcd6a76c0 100644 --- a/src/art/vector_revamp/vectorRevampedArtControl.js +++ b/src/art/vector_revamp/vectorRevampedArtControl.js @@ -1,8 +1,46 @@ /* eslint-disable camelcase */ window.RevampedVectorArt = function(slave) { + return App.Art.elementToMarkup(App.Art.revampedVectorArtElement(slave)); +}; + +/** + * @param {App.Entity.SlaveState} slave + * @returns {DocumentFragment} + */ +App.Art.revampedVectorArtElement = function(slave) { + /** + * @param {string} id + * @returns {HTMLElement} + */ + function useSvg(id) { + const cache = App.Data.Art.VectorRevamp; + /** @type {HTMLElement} */ + const res = cache.nodes.children.item(cache.dict.get(id)).children.item(0).cloneNode(true); + res.setAttribute("class", T.art_display_class); + let transformNodes = res.querySelectorAll('g[data-transform]'); + for (const node of transformNodes) { + switch (node.getAttribute("data-transform")) { + case "boob_left": + node.setAttribute("transform", T.revampedVectorArtControl.boobLeftArtTransform); + break; + case "boob_right": + node.setAttribute("transform", T.revampedVectorArtControl.boobRightArtTransform); + break; + case "boob_outfit": + node.setAttribute("transform", T.revampedVectorArtControl.boobOutfitArtTransform); + break; + case "pussy_tattoo_text": + node.textContent = T.revampedVectorArtControl.pubicTattooText; + break; + // seem to be no default art transform? + } + } + + return res; + } + const V = State.variables; const T = State.temporary; - let r; if (T.art_display_id > 0) { T.art_display_id++; @@ -14,7 +52,11 @@ window.RevampedVectorArt = function(slave) { /* Using JS from vectorRevampedArtControl.tw*/ T.revampedVectorArtControl = getVectorArtRevampedControl(T.art_display_class, slave, V.seeVectorArtHighlights, V.showBodyMods); - r = `<style>${T.revampedVectorArtControl.StylesCss}</style>`; + const res = document.createDocumentFragment(); + const style = document.createElement("style"); + style.innerHTML = T.revampedVectorArtControl.StylesCss; + res.appendChild(style); + T.revampedArtLayers = T.revampedVectorArtControl.Layers; T.art_transform = T.revampedVectorArtControl.artTransform; T.boob_right_art_transform = T.revampedVectorArtControl.boobRightArtTransform; @@ -22,9 +64,9 @@ window.RevampedVectorArt = function(slave) { T.boob_outfit_art_transform = T.revampedVectorArtControl.boobOutfitArtTransform; T.art_pussy_tattoo_text = T.revampedVectorArtControl.pubicTattooText; - T.revampedArtLayers.forEach(function(s) { r += jsInclude(s); }); + T.revampedArtLayers.forEach(function(s) { res.appendChild(useSvg(s)); }); - return r; + return res; }; window.getVectorArtRevampedControl = function(artDisplayClass, artSlave, globalShowHighlights, globalShowBodyMods) { diff --git a/src/debugging/debugJS.js b/src/debugging/debugJS.js index 6b8110b7a06ef57f3de857ed2fea157d267d6e4c..efce11a2103f244ac1a8ab41e25fe42acf783e38 100644 --- a/src/debugging/debugJS.js +++ b/src/debugging/debugJS.js @@ -118,3 +118,9 @@ App.Debug.dumpGameState = function() { SugarCube.Config.saves.onSave = oldHandler; } }; + +App.Debug.slaveSummaryText = function(idx) { + let span = document.createElement("span"); + span.appendChild(SlaveSummaryUncached(State.variables.slaves[idx])); + return span.outerHTML; +}; diff --git a/src/gui/svgFilters.tw b/src/gui/svgFilters.tw index 42e0b12951599b547d7562aeff5ca1a93c23ba12..14dd0a0cdb527e8a2a7cedbdf6967cf7238dc1f3 100644 --- a/src/gui/svgFilters.tw +++ b/src/gui/svgFilters.tw @@ -1,6 +1,5 @@ :: SVG filters -<html> <svg class="defs-only" style="width: 0; height: 0; position: absolute;"> <filter id="skin-black" color-interpolation-filters="sRGB"> <feColorMatrix type="matrix" values="0.15 0 0 0 0 0 0.1 0 0 0 0 0 0.05 0 0 0 0 0 1 0"/> @@ -213,4 +212,3 @@ <feColorMatrix type="matrix" values="0.7 0 0 0 0.5 0 0.7 0 0 0.5 0 0 0.5 0 0.4 0 0 0 1 0"/> </filter> </svg> -</html> diff --git a/src/init/setupVars.tw b/src/init/setupVars.tw index 6f437d960e46d5937951aacf190f83397a3bfdc0..4e730e52c070eeff2364720216a3a43317c4363b 100644 --- a/src/init/setupVars.tw +++ b/src/init/setupVars.tw @@ -2278,3 +2278,5 @@ Then pick _namePool.random(), or display those names as possible choices, or do "yellow":"yellow", "yellowgreen":"yellowgreen" }>> + +<<run App.Art.cacheArtData()>> diff --git a/src/js/assignJS.js b/src/js/assignJS.js index e75c3a4fc7432fdb98cdef6442a8afedab23f3b1..ad44b9a7a4dec3834c58f4018187a20521b650fc 100644 --- a/src/js/assignJS.js +++ b/src/js/assignJS.js @@ -614,7 +614,12 @@ App.UI.jobLinks = function() { App.Entity.facilities.servantsQuarters ]; - return {assignments: assignmentLinks, transfers: transferLinks}; + return { + assignments: assignmentLinks, + transfers: transferLinks, + assignmentsFragment: assignmentsFragment, + transfersFragment: transfersFragment + }; /** * Generates assignment links @@ -658,6 +663,63 @@ App.UI.jobLinks = function() { return transfers.join(' | '); } + + /** + * + * @param {number} index + * @param {string} passage + * @param {assignmentCallback} [callback] + * @returns {DocumentFragment} + */ + function assignmentsFragment(index, passage, callback) { + let penthouseJobs = App.Entity.facilities.penthouse.assignmentLinkElements(index, undefined, passage, callback); + const slave = App.Utils.slaveByIndex(index); + const sp = getPronouns(slave); + + if (slave.fuckdoll === 0) { + const assignment = "choose her own job"; + if (slave.assignment !== assignment) { + penthouseJobs.push( + App.UI.DOM.assignmentLink(State.variables.slaves[index], + assignment, passage, callback, `Let ${sp.object} choose`)); + } + } else { + penthouseJobs.push(App.UI.DOM.disabledLink(`Let ${sp.object} choose`, ["Fuckdolls can't choose their job"])); + } + let res = document.createDocumentFragment(); + // there is always at least one job + res.appendChild(penthouseJobs[0]); + for (let i = 1; i < penthouseJobs.length; ++i) { + res.appendChild(document.createTextNode(" | ")); + res.appendChild(penthouseJobs[i]); + } + return res; + } + + function transfersFragment(index) { + /** @type {HTMLElement[]} */ + const transfers = []; + const slave = App.Utils.slaveByIndex(index); + + for (const f of facilitiesOrder) { + if (!f.established) { continue; } + const rejects = f.canHostSlave(slave); + if (rejects.length === 0) { + transfers.push(f.transferLinkElement(index, undefined, passage())); + } else { + transfers.push(App.UI.DOM.disabledLink(f.genericName, rejects)); + } + } + + let res = document.createDocumentFragment(); + // there is always at least one job + res.appendChild(transfers[0]); + for (let i = 1; i < transfers.length; ++i) { + res.appendChild(document.createTextNode(" | ")); + res.appendChild(transfers[i]); + } + return res; + } }(); App.UI.SlaveInteract = { diff --git a/src/js/quickListJS.js b/src/js/quickListJS.js index f8c514eb9f238acf52d3aa0932a9ce04d846a173..fe4e110b654bbef3eba912082f63d337e127313b 100644 --- a/src/js/quickListJS.js +++ b/src/js/quickListJS.js @@ -30,18 +30,20 @@ window.sortButtonsByTrust = function() { }; window.quickListBuildLinks = function() { - $("[data-scroll-to]").click(function() { - let $this = $(this), - $toElement = $this.attr('data-scroll-to'); - // note the * 1 enforces $offset to be an integer, without - // it we scroll to True, which goes nowhere fast. - let $offset = $this.attr('data-scroll-offset') * 1 || 0; - let $speed = $this.attr('data-scroll-speed') * 1 || 500; - // Use javascript scrollTop animation for in page navigation. - $('html, body').animate({ - scrollTop: $($toElement).offset().top + $offset - }, $speed); - }); + $("[data-scroll-to]").click(App.UI.quickBtnScrollToHandler); +}; + +App.UI.quickBtnScrollToHandler = function() { + let $this = $(this), + $toElement = $this.attr('data-scroll-to'); + // note the * 1 enforces $offset to be an integer, without + // it we scroll to True, which goes nowhere fast. + let $offset = $this.attr('data-scroll-offset') * 1 || 0; + let $speed = $this.attr('data-scroll-speed') * 1 || 500; + // Use javascript scrollTop animation for in page navigation. + $('html, body').animate({ + scrollTop: $($toElement).offset().top + $offset + }, $speed); }; window.sortIncubatorPossiblesByName = function() { diff --git a/src/js/slaveListing.js b/src/js/slaveListing.js index ab3d2b8d0a9e33b330fd047b6eb847be2041a593..7e8f527d4f7b763b8e252349452b2fad8f98ce16 100644 --- a/src/js/slaveListing.js +++ b/src/js/slaveListing.js @@ -13,6 +13,14 @@ App.UI.SlaveList = {}; * @param {number} index * @returns {string} */ + + /** + * @callback slaveToElement + * @param {App.Entity.SlaveState} slave + * @param {number} index + * @returns {HTMLElement|DocumentFragment} + */ + App.UI.SlaveList.render = function() { 'use strict'; let V; @@ -26,25 +34,36 @@ App.UI.SlaveList.render = function() { // potentially can be a problem if played long enough to reach Number.MAX_SAFE_INTEGER let listID = Number.MIN_SAFE_INTEGER; - return renderList; + const tabStr = "    "; // 4 * + + /** @type {Object.<number, Node>}*/ + const readyResults = { + + }; + + return { + listMarkup: listMarkup, + listDOM: listDOM + }; /** * @param {number[]} indices * @param {Array.<{index: number, rejects: string[]}>} rejectedSlaves - * @param {slaveTextGenerator} interactionLink - * @param {slaveTextGenerator} [postNote] - * @returns {string} + * @param {slaveToElement} interactionLink + * @param {slaveToElement} [postNote] + * @returns {DocumentFragment} */ - function renderList(indices, rejectedSlaves, interactionLink, postNote) { + function listDOM(indices, rejectedSlaves, interactionLink, postNote) { V = State.variables; passageName = passage(); slaves = V.slaves; V.assignTo = passageName; // would be passed to the "Assign" passage slaveImagePrinted = (V.seeImages === 1) && (V.seeSummaryImages === 1); - let res = []; + let res = document.createDocumentFragment(); + if (V.useSlaveListInPageJSNavigation === 1) { - res.push(createQuickList(indices)); + res.appendChild(createQuickList(indices)); } const fcs = App.Entity.facilities; @@ -62,49 +81,96 @@ App.UI.SlaveList.render = function() { for (const _si of indices) { let ss = renderSlave(_si, interactionLink, showTransfers, postNote); - res.push(`<div id="slave-${slaves[_si].ID}" style="clear:both">${ss}</div>`); + let slaveDiv = document.createElement("div"); + slaveDiv.id = `slave-${slaves[_si].ID}`; + slaveDiv.classList.add("slaveSummary"); + slaveDiv.appendChild(ss); + res.appendChild(slaveDiv); } for (const rs of rejectedSlaves) { const slave = slaves[rs.index]; const rejects = rs.rejects; const slaveName = SlaveFullName(slave); - let rejectString = rejects.length === 1 ? - rejects[0] : - `${slaveName}: <ul>${rejects.map(e => `<li>${e}</li>`).join('')}</ul>`; - res.push(`<div id="slave_${slave.ID}" style="clear:both">${rejectString}</div>`); + let slaveDiv = document.createElement("div"); + slaveDiv.id = `slave-${slave.ID}`; + slaveDiv.style.setProperty("clear", "both"); + if (rejects.length === 1) { + slaveDiv.innerHTML = rejects[0]; + } else { + slaveDiv.appendChild(document.createTextNode(`${slaveName}: `)); + let ul = document.createElement("ul"); + for (const rr of rejects) { + const li = document.createElement("li"); + li.innerHTML = rr; + ul.appendChild(li); + } + slaveDiv.appendChild(ul); + } + res.appendChild(slaveDiv); } + return res; + } + + /** + * @param {number[]} indices + * @param {Array.<{index: number, rejects: string[]}>} rejectedSlaves + * @param {slaveToElement} interactionLink + * @param {slaveToElement} [postNote] + * @returns {string} + */ + function listMarkup(indices, rejectedSlaves, interactionLink, postNote) { + const listIDStr = `slave-list-${listID}`; + readyResults[listID] = listDOM(indices, rejectedSlaves, interactionLink, postNote); + $(document).one(':passagedisplay', function() { - $('[data-quick-index]').unbind().click(function() { - let which = this.attributes["data-quick-index"].value; - let quick = $("div#list_index" + which); - quick.toggleClass("hidden"); - }); - quickListBuildLinks(); + for (const e of document.querySelectorAll('[id^=slave-list]')) { + const id = e.getAttribute("data-listId"); + if (readyResults.hasOwnProperty(id)) { + if (e.childNodes.length > 0) { + e.innerHTML = ''; + } + e.appendChild(readyResults[id]); + delete readyResults[id]; + } + } }); - if (V.useSlaveListInPageJSNavigation === 1) { - listID++; - } + let resMarkup = `<div id="${listIDStr}" data-listId="${listID}"></div>`; + ++listID; - return res.join(""); + return resMarkup; } /** * @param {number} index - * @param {slaveTextGenerator} interactionLink + * @param {slaveToElement} interactionLink * @param {boolean} showTransfers - * @param {slaveTextGenerator} [postNote] - * @returns {string} + * @param {slaveToElement} [postNote] + * @returns {DocumentFragment} */ function renderSlave(index, interactionLink, showTransfers, postNote) { - let res = []; + let res = document.createDocumentFragment(); + if (V.lineSeparations === 0) { + res.appendChild(document.createElement("br")); + } else { + const hr = document.createElement("hr"); + hr.style.margin = "0"; + res.appendChild(hr); + } const slave = slaves[index]; - res.push(dividerAndImage(slave)); - res.push(interactionLink(slave, index)); + if ((V.seeImages === 1) && (V.seeSummaryImages === 1)) { + let imgDiv = document.createElement("div"); + imgDiv.classList.add("imageRef"); + imgDiv.classList.add("smlImg"); + imgDiv.appendChild(App.Art.SlaveArtElement(slave, 1)); + res.appendChild(imgDiv); + } + // res.push(dividerAndImage(slave)); + res.appendChild(interactionLink(slave, index)); if ((slave.choosesOwnClothes === 1) && (slave.clothes === "choosing her own clothes")) { const _oldDevotion = slave.devotion; @@ -116,53 +182,86 @@ App.UI.SlaveList.render = function() { slave.trust = Math.trunc(slave.trust); slave.devotion = Math.trunc(slave.devotion); slave.health = Math.trunc(slave.health); - res.push(' will '); + res.appendChild(document.createTextNode(' will ')); + const assignment = document.createElement("span"); if ((slave.assignment === "rest") && (slave.health >= -20)) { - res.push(`<strong><u><span class="lawngreen">rest</span></u></strong>`); + assignment.className = "freeAssignment"; + assignment.innerText = slave.assignment; } else if ((slave.assignment === "stay confined") && ((slave.devotion > 20) || ((slave.trust < -20) && (slave.devotion >= -20)) || ((slave.trust < -50) && (slave.devotion >= -50)))) { - res.push(`<strong><u><span class="lawngreen">stay confined.</span></u></strong>`); + assignment.innerText = slave.assignment; if (slave.sentence > 0) { - res.push(` (${slave.sentence} weeks)`); + assignment.innerText += ` (${slave.sentence} weeks)`; } } else if (slave.choosesOwnAssignment === 1) { - res.push('choose her own job'); + assignment.innerText = 'choose her own job'; } else { - res.push(slave.assignment); + assignment.innerText = slave.assignment; if (slave.sentence > 0) { - res.push(` ${slave.sentence} weeks`); + assignment.innerText += ` ${slave.sentence} weeks`; } } - res.push('. '); + assignment.innerText += ". "; + res.appendChild(assignment); if ((V.displayAssignments === 1) && (passageName === "Main") && (slave.ID !== V.HeadGirl.ID) && (slave.ID !== V.Recruiter.ID) && (slave.ID !== V.Bodyguard.ID)) { - res.push(App.UI.jobLinks.assignments(index, "Main")); + res.appendChild(App.UI.jobLinks.assignmentsFragment(index, "Main")); } if (showTransfers) { - res.push('<br>Transfer to: ' + App.UI.jobLinks.transfers(index)); - } - res.push('<br/>'); - - if (slaveImagePrinted) { - res.push(' '); + res.appendChild(document.createElement("br")); + res.appendChild(document.createTextNode('Transfer to: ')); + res.appendChild(App.UI.jobLinks.transfersFragment(index)); } - clearSummaryCache(); - res.push(SlaveSummary(slave)); + res.appendChild(SlaveSummaryUncached(slave)); if (postNote !== undefined) { - res.push('<br>'); - res.push(postNote(slave, index)); + const pn = postNote(slave, index); + if (pn) { + res.appendChild(document.createElement('br')); + res.appendChild(pn); + } } - return res.join(''); + return res; } /** * @param {number[]} indices - * @returns {string} + * @returns {DocumentFragment} */ function createQuickList(indices) { - let res = ""; + /** + * + * @param {Node} container + * @param {string} tagName + * @param {string} [content] + * @param {string|string[]} [classNames] + * @param {Object.<string, any>} [attributes] + * @returns {HTMLElement} + */ + function makeElement(container, tagName, content, classNames, attributes) { + let res = document.createElement(tagName); + container.appendChild(res); + if (content) { + res.textContent = content; + } + if (Array.isArray(classNames)) { + for (const c of classNames) { + res.classList.add(c); + } + } else if (classNames !== undefined) { + res.classList.add(classNames); + } + + if (attributes) { + for (const [k, v] of Object.entries(attributes)) { + res.setAttribute(k, v); + } + } + return res; + } + + const res = document.createDocumentFragment(); /* Useful for finding weird combinations — usages of this passage that don't yet generate the quick index. * <<print 'pass/count/indexed/flag::[' + passageName + '/' + _Count + '/' + _indexed + '/' + $SlaveSummaryFiler + ']'>> @@ -174,19 +273,24 @@ App.UI.SlaveList.render = function() { if (/Select/i.test(passageName)) { _offset = -25; } - res += "<br />"; + res.appendChild(document.createElement("br")); /* * we want <button data-quick-index="<<= listID>>">... */ - const _buttonAttributes = { - 'id': `quick-list-toggle${listID}`, - 'data-quick-index': listID + const quickIndexBtn = document.createElement("button"); + res.appendChild(quickIndexBtn); + quickIndexBtn.id = `quick-list-toggle${listID}`; + quickIndexBtn.setAttribute('data-quick-index', listID.toString()); + quickIndexBtn.onclick = function(ev) { + let which = ev.target.attributes["data-quick-index"].value; + let quick = $("div#list_index" + which); + quick.toggleClass("hidden"); }; - res += App.UI.htag("Quick Index", _buttonAttributes, 'button'); /* * we want <div id="list_index3" class=" hidden">... */ - let listIndexContent = ""; + const listIndex = makeElement(res, "div", undefined, "hidden"); + listIndex.id = `list_index${listID}`; for (const _ssii of indices) { const _IndexSlave = slaves[_ssii]; @@ -204,71 +308,59 @@ App.UI.SlaveList.render = function() { } if (_buttons.length > 0) { V.sortQuickList = V.sortQuickList || 'Devotion'; - listIndexContent += `//Sorting:// ''<span id="qlSort">$sortQuickList</span>.'' `; - listIndexContent += '<<link "Sort by Devotion">>' + - '<<set $sortQuickList = "Devotion" >>' + - '<<replace "#qlSort">> $sortQuickList <</replace>>' + - '<<run' + '$("#qlWrapper").removeClass("trust").addClass("devotion");' + 'sortButtonsByDevotion();' + '>>' + - '<</link>> | ' + - '<<link "Sort by Trust">>' + - '<<set $sortQuickList = "Trust">>' + - '<<replace "#qlSort">> $sortQuickList <</replace>>' + - '<<run' + '$("#qlWrapper").removeClass("devotion").addClass("trust");' + 'sortButtonsByTrust();' + '>>' + - '<</link>>' + - '<br/>'; - listIndexContent += '<div id="qlWrapper" class="quicklist devotion">'; + makeElement(listIndex, "em", "Sorting: "); + const qlSort = makeElement(listIndex, "span", V.sortQuickList, "strong"); + qlSort.id = "qlSort"; + listIndex.appendChild(document.createTextNode(". ")); + const linkSortByDevotion = makeElement(listIndex, "a", "Sort by Devotion"); + linkSortByDevotion.onclick = (ev) => { + ev.preventDefault(); + State.variables.sortQuickList = "Devotion"; + $("#qlSort").text(State.variables.sortQuickList); + $("#qlWrapper").removeClass("trust").addClass("devotion"); + sortButtonsByDevotion(); + }; + const linkSortByTrust = makeElement(listIndex, "a", "Sort by Trust"); + linkSortByTrust.onclick = (ev) => { + ev.preventDefault(); + State.variables.sortQuickList = "Trust"; + $("#qlSort").text(State.variables.sortQuickList); + $("#qlWrapper").removeClass("devotion").addClass("trust"); + sortButtonsByTrust(); + }; + makeElement(listIndex, "br"); + const qlWrapper = makeElement(listIndex, "div", undefined, ["quicklist", "devotion"]); + qlWrapper.id = "qlWrapper"; for (const _button of _buttons) { - const _buttonSlaveName = _button['data-name']; - listIndexContent += App.UI.htag(_buttonSlaveName, _button, 'button'); + const btn = makeElement(listIndex, 'button', _button['data-name'], undefined, _button); + btn.onclick = App.UI.quickBtnScrollToHandler; } - listIndexContent += '</div>'; } - res += App.UI.htag(listIndexContent, { - id: `list_index${listID}`, - class: 'hidden' - }); } return res; } - - function SlaveArt(slave, option) { - return `<<SlaveArtById ${slave.ID} ${option}>>`; - } - - function slaveImage(s) { - return `<div class="imageRef smlImg">${SlaveArt(s, 1)}</div>`; - } - - function dividerAndImage(s, showImage) { - showImage = showImage || true; - const r = [V.lineSeparations === 0 ? "<br>" : "<hr style=\"margin:0\">"]; - if (showImage && (V.seeImages === 1) && (V.seeSummaryImages === 1)) { - r.push(slaveImage(s)); - } - return r.join(""); - } }(); App.UI.SlaveList.Decoration = {}; /** * returns "HG", "BG", "PA", and "RC" prefixes * @param {App.Entity.SlaveState} slave - * @returns {string} + * @returns {HTMLElement} */ App.UI.SlaveList.Decoration.penthousePositions = (slave) => { if (App.Data.Facilities.headGirlSuite.manager.assignment === slave.assignment) { - return '<strong><span class="lightcoral">HG</span></strong>'; + return App.UI.DOM.makeSpan('HG', ['lightcoral', 'strong']); } if (App.Data.Facilities.penthouse.manager.assignment === slave.assignment) { - return '<strong><span class="lightcoral">RC</span></strong>'; + return App.UI.DOM.makeSpan('RC', ['lightcoral', 'strong']); } if (App.Data.Facilities.armory.manager.assignment === slave.assignment) { - return '<strong><span class="lightcoral">BG</span></strong>'; + return App.UI.DOM.makeSpan('BG', ['lightcoral', 'strong']); } if (Array.isArray(State.variables.personalAttention) && State.variables.personalAttention.findIndex(s => s.ID === slave.ID) !== -1) { - return '<strong><span class="lightcoral">PA</span></strong>'; + return App.UI.DOM.makeSpan('PA', ['lightcoral', 'strong']); } - return ''; + return null; }; App.UI.SlaveList.SlaveInteract = {}; @@ -276,27 +368,37 @@ App.UI.SlaveList.SlaveInteract = {}; /** * @param {App.Entity.SlaveState} slave * @param {number} index - * @returns {string} + * @returns {HTMLElement} */ App.UI.SlaveList.SlaveInteract.stdInteract = (slave, index) => - App.UI.passageLink(SlaveFullName(slave), 'Slave Interact', `$activeSlave = $slaves[${index}]`); + App.UI.DOM.passageLink(SlaveFullName(slave), 'Slave Interact', () => { App.Utils.setActiveSlaveByIndex(index); }); /** * @param {App.Entity.SlaveState} slave * @param {number} index - * @returns {string} + * @returns {DocumentFragment|HTMLElement} */ App.UI.SlaveList.SlaveInteract.penthouseInteract = (slave, index) => { - return App.UI.SlaveList.Decoration.penthousePositions(slave) + ' ' + App.UI.SlaveList.SlaveInteract.stdInteract(slave, index); + let decoration = App.UI.SlaveList.Decoration.penthousePositions(slave); + let stdLink = App.UI.SlaveList.SlaveInteract.stdInteract(slave, index); + if (decoration) { + let fr = document.createDocumentFragment(); + fr.appendChild(decoration); + fr.appendChild(document.createTextNode(' ')); + fr.appendChild(stdLink); + return fr; + } + return stdLink; }; /** * @param {App.Entity.SlaveState} slave - * @returns {string} + * @returns {HTMLElement} */ App.UI.SlaveList.SlaveInteract.personalAttention = (slave) => - App.UI.passageLink(SlaveFullName(slave), undefined, `App.UI.selectSlaveForPersonalAttention(${slave.ID});`); + App.UI.DOM.passageLink(SlaveFullName(slave), undefined, + () => { App.UI.selectSlaveForPersonalAttention(slave.ID); }); /** * Adds/removes a slave with the given id to/from the personal attention array @@ -382,9 +484,10 @@ App.UI.SlaveList.listSJFacilitySlaves = function(facility, facilityPassage, show if (facility.hostedSlaves > 0) { let facilitySlaves = job.employeesIndices(); SlaveSort.indices(facilitySlaves); - r += App.UI.tabbar.makeTab("remove", App.UI.SlaveList.render(facilitySlaves, [], + r += App.UI.tabbar.makeTab("remove", App.UI.SlaveList.render.listMarkup(facilitySlaves, [], App.UI.SlaveList.SlaveInteract.stdInteract, - (slave, index) => App.UI.passageLink(`Retrieve ${getPronouns(slave).object} from ${facility.name}`, "Retrieve", `$i = ${index}`))); + (slave, index) => App.UI.DOM.passageLink(`Retrieve ${getPronouns(slave).object} from ${facility.name}`, "Retrieve", + () => { variables().i = index; }))); } else { r += App.UI.tabbar.makeTab("remove", `<em>${capFirstChar(facility.name)} is empty for the moment</em>`); } @@ -406,9 +509,10 @@ App.UI.SlaveList.listSJFacilitySlaves = function(facility, facilityPassage, show passedSlaves.push(idx); } }, []); - return App.UI.SlaveList.render(passedSlaves, rejectedSlaves, + return App.UI.SlaveList.render.listMarkup(passedSlaves, rejectedSlaves, App.UI.SlaveList.SlaveInteract.stdInteract, - (slave, index) => App.UI.passageLink(`Send ${getPronouns(slave).object} to ${facility.name}`, "Assign", `$i = ${index}`)); + (slave, index) => App.UI.DOM.passageLink(`Send ${getPronouns(slave).object} to ${facility.name}`, "Assign", + () => { variables().i = index; })); } if (facility.hasFreeSpace) { const assignableSlaveIdxs = job.desc.partTime ? @@ -438,6 +542,20 @@ App.UI.SlaveList.listSJFacilitySlaves = function(facility, facilityPassage, show return r; }; +/** + * @param {string[]} classNames + */ +App.UI.SlaveList.makeNameDecorator = function(classNames) { + return (slave) => { + const r = document.createElement("span"); + for (const c of classNames) { + r.classList.add(c); + } + r.textContent = SlaveFullName(slave); + return r; + }; +}; + /** * @returns {string} */ @@ -458,10 +576,11 @@ App.UI.SlaveList.listNGPSlaves = function() { if (V.slavesToImport > 0) { const importedSlavesIndices = slaves.reduce((acc, s, i) => { if (s.assignment === NGPassignment) { acc.push(i); } return acc; }, []); SlaveSort.indices(importedSlavesIndices); - r += App.UI.tabbar.makeTab("remove", App.UI.SlaveList.render(importedSlavesIndices, [], - (s) => `<u><strong><span class="pink">${SlaveFullName(s)}</span></strong></u>`, - (s, i) => App.UI.passageLink('Remove from import list', thisPassage, - `$slavesToImport -= 1, removeJob(${App.Utils.slaveRefString(i)}, "${NGPassignment}")`))); + r += App.UI.tabbar.makeTab("remove", App.UI.SlaveList.render.listMarkup(importedSlavesIndices, [], + App.UI.SlaveList.makeNameDecorator(["emphasizedSlave", "pink"]), + (s, i) => App.UI.DOM.passageLink('Remove from import list', thisPassage, + () => { variables().slavesToImport -= 1; removeJob(variables().slaves[i], NGPassignment); } + ))); } else { r += App.UI.tabbar.makeTab("remove", `<em>No slaves will go with you to the new game</em>`); } @@ -469,10 +588,11 @@ App.UI.SlaveList.listNGPSlaves = function() { if (V.slavesToImport < V.slavesToImportMax) { const slavesToImportIndices = slaves.reduce((acc, s, i) => { if (s.assignment !== NGPassignment) { acc.push(i); } return acc; }, []); SlaveSort.indices(slavesToImportIndices); - r += App.UI.tabbar.makeTab("assign", App.UI.SlaveList.render(slavesToImportIndices, [], - (s) => `<u><strong><span class="pink">${SlaveFullName(s)}</span></strong></u>`, - (s, i) => App.UI.passageLink('Add to import list', thisPassage, - `$slavesToImport += 1, assignJob(${App.Utils.slaveRefString(i)}, "${NGPassignment}")`))); + r += App.UI.tabbar.makeTab("assign", App.UI.SlaveList.render.listMarkup(slavesToImportIndices, [], + App.UI.SlaveList.makeNameDecorator(["emphasizedSlave", "pink"]), + (s, i) => App.UI.DOM.passageLink('Add to import list', thisPassage, + () => { variables().slavesToImport += 1; assignJob(variables().slaves[i], NGPassignment); } + ))); } else { r += App.UI.tabbar.makeTab("assign", `<strong>Slave import limit reached</strong>`); } @@ -492,9 +612,9 @@ App.UI.SlaveList.displayManager = function(facility, selectionPassage) { selectionPassage = selectionPassage || `${managerCapName} Select`; const manager = facility.manager.currentEmployee; if (manager) { - return this.render([App.Utils.slaveIndexForId(manager.ID)], [], + return this.render.listMarkup([App.Utils.slaveIndexForId(manager.ID)], [], App.UI.SlaveList.SlaveInteract.stdInteract, - () => App.UI.passageLink(`Change or remove ${managerCapName}`, selectionPassage, "")); + () => App.UI.DOM.passageLink(`Change or remove ${managerCapName}`, selectionPassage)); } else { return `You do not have a slave serving as a ${managerCapName}. ${App.UI.passageLink(`Appoint one`, selectionPassage, "")}`; } @@ -526,12 +646,12 @@ App.UI.SlaveList.penthousePage = function() { if (V.HeadGirl) { /** @type {App.Entity.SlaveState} */ const HG = V.HeadGirl; - r += `<strong><u>${span(SlaveFullName(HG), "pink")}</u></strong> is serving as your Head Girl`; + r += `${span(SlaveFullName(HG), "emphasizedSlave pink")} is serving as your Head Girl`; if (thisArcology.FSEgyptianRevivalistLaw === 1) { r += ' and Consort'; } r += `. <strong> ${span(App.UI.passageLink("Manage Head Girl", "HG Select"), null, "manageHG")}</strong> ${span("[H]", "cyan")}`; - r += App.UI.SlaveList.render([App.Utils.slaveIndexForId(HG.ID)], [], + r += App.UI.SlaveList.render.listMarkup([App.Utils.slaveIndexForId(HG.ID)], [], App.UI.SlaveList.SlaveInteract.penthouseInteract); } else { if (V.slaves.length > 1) { @@ -550,7 +670,7 @@ App.UI.SlaveList.penthousePage = function() { /** @type {App.Entity.SlaveState} */ const RC = V.Recruiter; const p = getPronouns(RC); - r += `<strong><u>${span(SlaveFullName(RC), "pink")}</u></strong> is working `; + r += `${span(SlaveFullName(RC), "emphasizedSlave pink")} is working `; if (V.recruiterTarget !== "other arcologies") { r += 'to recruit girls'; } else { @@ -563,7 +683,7 @@ App.UI.SlaveList.penthousePage = function() { } } r += `${span('. <strong>' + App.UI.passageLink("Manage Recruiter", "Recruiter Select") + '</strong>', null, "manageRecruiter")} ${span("[U]", "cyan")}`; - r += App.UI.SlaveList.render([App.Utils.slaveIndexForId(RC.ID)], [], + r += App.UI.SlaveList.render.listMarkup([App.Utils.slaveIndexForId(RC.ID)], [], App.UI.SlaveList.SlaveInteract.penthouseInteract); } else { r += `You have ${span("not", "red")} selected a Recruiter. `; @@ -575,14 +695,14 @@ App.UI.SlaveList.penthousePage = function() { /** @type {App.Entity.SlaveState} */ const BG = V.Bodyguard; if (BG) { - r += `<strong><u>${span(SlaveFullName(BG), "pink")}</u></strong> is serving as your bodyguard. `; - r += span(`<strong>${App.UI.passageLink("Manage Bodyguard", "BG Select")}</strong>`, null, "manageBG") + + r += `${span(SlaveFullName(BG), "emphasizedSlave pink")} is serving as your bodyguard. `; + r += span(`<strong>${App.UI.passageLink("Manage Bodyguard", "BG Select")}</strong> `, null, "manageBG") + span("[B]", "cyan"); - r += App.UI.SlaveList.render([App.Utils.slaveIndexForId(BG.ID)], [], + r += App.UI.SlaveList.render.listMarkup([App.Utils.slaveIndexForId(BG.ID)], [], App.UI.SlaveList.SlaveInteract.penthouseInteract); } else { r += `You have ${span("not", "red")} selected a Bodyguard. `; - r += span(`<strong>${App.UI.passageLink("Select one", "BG Select")}</strong>`, null, "manageBG") + + r += span(`<strong>${App.UI.passageLink("Select one", "BG Select")}</strong> `, null, "manageBG") + span("[B]", "cyan"); } @@ -633,7 +753,7 @@ App.UI.SlaveList.penthousePage = function() { SlaveSort.indices(employeesIndices); return { n: employeesIndices.length, - text: App.UI.SlaveList.render(employeesIndices, [], App.UI.SlaveList.SlaveInteract.penthouseInteract) + text: App.UI.SlaveList.render.listMarkup(employeesIndices, [], App.UI.SlaveList.SlaveInteract.penthouseInteract) }; } @@ -656,7 +776,14 @@ App.UI.SlaveList.penthousePage = function() { function _updateList(job) { State.temporary.mainPageUpdate.job = job; - App.UI.replace('#' + listElementId, _slavesForJob(job).text); + const e = document.getElementById(listElementId); + e.innerHTML = ''; + const employeesIndices = job === 'all' ? ph.employeesIndices() : ph.job(job).employeesIndices(); + if (employeesIndices.length === 0) { + return; + } + SlaveSort.indices(employeesIndices); + e.appendChild(App.UI.SlaveList.render.listDOM(employeesIndices, [], App.UI.SlaveList.SlaveInteract.penthouseInteract)); } /** @@ -748,7 +875,7 @@ App.UI.SlaveList.penthousePage = function() { const penthouseSlavesIndices = ph.employeesIndices(); SlaveSort.indices(penthouseSlavesIndices); tabs.push(makeTabDesc('all', `All (${penthouseSlavesIndices.length})`, - this.render(penthouseSlavesIndices, [], App.UI.SlaveList.SlaveInteract.penthouseInteract))); + this.render.listMarkup(penthouseSlavesIndices, [], App.UI.SlaveList.SlaveInteract.penthouseInteract))); r += '<div class="tab">'; @@ -805,15 +932,15 @@ App.UI.SlaveList.slaveSelectionList = function() { * @typedef ListOptions * @property {slaveFilterCallbackReasoned|slaveFilterCallbackSimple} filter * @property {slaveTestCallback} [expCheck] - * @property {slaveTextGenerator} interactionLink - * @property {slaveTextGenerator} [postNote] + * @property {slaveToElement} interactionLink + * @property {slaveToElement} [postNote] */ /** * @param {slaveFilterCallbackReasoned|slaveFilterCallbackSimple} filter - * @param {slaveTextGenerator} interactionLink + * @param {slaveToElement} interactionLink * @param {slaveTestCallback} [experianceChecker] - * @param {slaveTextGenerator} [postNote] + * @param {slaveToElement} [postNote] * @returns {string} */ function selection(filter, interactionLink, experianceChecker, postNote) { @@ -831,7 +958,9 @@ App.UI.SlaveList.slaveSelectionList = function() { } function _updateList(assignment) { - App.UI.replace('#' + selectionElementId, _listSlaves(assignment, State.temporary.slaveSelection)); + const e = document.getElementById(selectionElementId); + e.innerHTML = ''; + e.appendChild(_listSlaves(assignment, State.temporary.slaveSelection)); } /** * Displays assignment filter links, whose action are generated by the callback @@ -874,7 +1003,7 @@ App.UI.SlaveList.slaveSelectionList = function() { * * @param {string} assignmentStr * @param {ListOptions} options - * @returns {string} + * @returns {DocumentFragment} */ function _listSlaves(assignmentStr, options) { /** @type {App.Entity.SlaveState[]} */ @@ -913,13 +1042,17 @@ App.UI.SlaveList.slaveSelectionList = function() { // done this way to test for tests presence only once const listPostNote = options.expCheck ? (options.postNote ? - (s, i) => options.expCheck(s) ? '<span class="lime">Has applicable career experience.</span><br>' : '' + options.postNote(s, i) : - (s) => options.expCheck(s) ? '<span class="lime">Has applicable career experience.</span>' : '') : + (s, i) => options.expCheck(s) ? App.UI.DOM.combineNodes( + App.UI.DOM.makeSpan("Has applicable career experience.", "lime"), + document.createElement("br"), + options.postNote(s, i) + ) : options.postNote(s, i) : + (s) => options.expCheck(s) ? App.UI.DOM.makeSpan("Has applicable career experience.", "lime") : null) : options.postNote ? (s, i) => options.postNote(s, i) : - () => ''; + () => null; - return App.UI.SlaveList.render(passingIndices, rejects, options.interactionLink, listPostNote); + return App.UI.SlaveList.render.listDOM(passingIndices, rejects, options.interactionLink, listPostNote); } }(); @@ -931,6 +1064,7 @@ App.UI.SlaveList.slaveSelectionList = function() { App.UI.SlaveList.facilityManagerSelection = function(facility, passage) { passage = passage || capFirstChar(facility.manager.desc.position) + " Workaround"; return this.slaveSelectionList(slave => facility.manager.canEmploy(slave), - (slave, index) => App.UI.passageLink(SlaveFullName(slave), passage, `$i = ${index}`), + (slave, index) => App.UI.DOM.passageLink(SlaveFullName(slave), passage, + () => { variables().i = index; }), slave => facility.manager.slaveHasExperience(slave)); }; diff --git a/src/js/slaveSummaryWidgets.js b/src/js/slaveSummaryWidgets.js index 1c333706ac884e9082dbf2bcb75d5010d437d548..5e2fb6551d7ac7add375b66214417553058f17d0 100644 --- a/src/js/slaveSummaryWidgets.js +++ b/src/js/slaveSummaryWidgets.js @@ -31,2429 +31,2152 @@ window.SlaveSummary = function SlaveSummary(slave) { window.SlaveSummaryUncached = (function() { "use strict"; let V; - let r; + /** @type {DocumentFragment} */ + let res; /** * @param {App.Entity.SlaveState} slave - * @returns {string} */ + * @returns {DocumentFragment} */ function SlaveSummaryUncached(slave) { V = State.variables; - r = ""; + res = document.createDocumentFragment(); + let para = makeParagraph(res); if (V.abbreviateDevotion === 1) { - short_devotion(slave); + short_devotion(slave, para); } else if (V.abbreviateDevotion === 2) { - long_devotion(slave); + long_devotion(slave, para); } if (slave.fuckdoll === 0) { if (V.abbreviateRules === 1) { - short_rules(slave); + short_rules(slave, para); } else if (V.abbreviateRules === 2) { - long_rules(slave); + long_rules(slave, para); } } if (slave.tired !== 0) { - r += `Tired.`; + addText(para, `Tired.`); } if (V.abbreviateDiet === 1) { - short_weight(slave); + short_weight(slave, para); } else if (V.abbreviateDiet === 2) { - long_weight(slave); + long_weight(slave, para); } if (V.abbreviateDiet === 1) { - short_diet(slave); + short_diet(slave, para); } else if (V.abbreviateDiet === 2) { - long_diet(slave); + long_diet(slave, para); } if (V.abbreviateHealth === 1) { - short_health(slave); + short_health(slave, para); } else if (V.abbreviateHealth === 2) { - long_health(slave); + long_health(slave, para); } if (V.abbreviateDrugs === 1) { - short_drugs(slave); + short_drugs(slave, para); } else if (V.abbreviateDrugs === 2) { - long_drugs(slave); + long_drugs(slave, para); } - if (V.abbreviateNationality + V.abbreviateGenitalia + V.abbreviatePhysicals + V.abbreviateSkills + V.abbreviateMental !== 0) { - r += `<br>`; - if (V.seeImages !== 1 || V.seeSummaryImages !== 1 || V.imageChoice === 1) { - r += " "; - } - } - V.desc = SlaveTitle(slave); - const first_letter = V.desc.substring(0, 1).toUpperCase(); - V.desc = first_letter + V.desc.substring(1); - r += `<strong><span class="coral">${V.desc}${V.abbreviatePhysicals === 2? '.' : ''}</span></strong> `; - if (V.seeRace === 1) { - r += `<span class="tan">`; - if (V.abbreviateRace === 1) { - short_race(slave); - } else if (V.abbreviateRace === 2) { - long_race(slave); - } - r += `</span> `; - } - if (V.abbreviateNationality === 1) { - short_nationality(slave); - } else if (V.abbreviateNationality === 2) { - long_nationality(slave); + + para = makeParagraph(res); + para.classList.add("pink"); + + makeSpan(para, `${capFirstChar(SlaveTitle(slave))}${V.abbreviatePhysicals === 2 ? '.' : ''}`, ["coral", "strong"]); + if (V.seeRace === 1 && V.abbreviateRace !== 0) { + makeSpan(para, V.abbreviateRace === 1 ? short_race(slave) : long_race(slave), "tan"); } - if (V.abbreviatePhysicals === 1) { - short_skin(slave); - } else { - r += `<span class="pink">${slave.skin.charAt(0).toUpperCase() + slave.skin.slice(1)} skin.</span> `; + if (V.abbreviateNationality !== 0) { + makeSpan(para, V.abbreviateNationality === 1 ? short_nationality(slave) : long_nationality(slave), "tan"); } + makeSpan(para, V.abbreviatePhysicals === 1 ? short_skin(slave) : `${capFirstChar(slave.skin)} skin.`); if (V.abbreviateGenitalia === 1) { - short_genitals(slave); + short_genitals(slave, para); } else if (V.abbreviateGenitalia === 2) { - long_genitals(slave); + long_genitals(slave, para); } if (V.abbreviatePhysicals === 1) { - short_age(slave); - short_face(slave); - short_eyes(slave); - short_ears(slave); + short_age(slave, para); + short_face(slave, para); + short_eyes(slave, para); + short_ears(slave, para); if (slave.markings !== "none") { - r += "Markings"; + makeSpan(para, "Markings"); } - short_lips(slave); - short_teeth(slave); - short_muscles(slave); - short_limbs(slave); - short_voice(slave); - short_tits_ass(slave); - short_hips(slave); - short_waist(slave); - short_implants(slave); - short_lactation(slave); - short_mods(slave); - r += `</span>`; + short_lips(slave, para); + short_teeth(slave, para); + short_muscles(slave, para); + short_limbs(slave, para); + short_voice(slave, para); + short_tits_ass(slave, para); + short_hips(slave, para); + short_waist(slave, para); + short_implants(slave, para); + short_lactation(slave, para); + short_mods(slave, para); } else if (V.abbreviatePhysicals === 2) { - long_age(slave); - long_face(slave); - long_eyes(slave); - long_ears(slave); - long_lips(slave); - long_teeth(slave); - long_muscles(slave); - long_limbs(slave); - long_voice(slave); - long_tits_ass(slave); - long_hips(slave); - long_waist(slave); - long_implants(slave); - long_lactation(slave); - long_mods(slave); + long_age(slave, para); + long_face(slave, para); + long_eyes(slave, para); + long_ears(slave, para); + long_lips(slave, para); + long_teeth(slave, para); + long_muscles(slave, para); + long_limbs(slave, para); + long_voice(slave, para); + long_tits_ass(slave, para); + long_hips(slave, para); + long_waist(slave, para); + long_implants(slave, para); + long_lactation(slave, para); + long_mods(slave, para); if (!jQuery.isEmptyObject(slave.brand)) { - r += `Branded.`; + makeSpan(para, `Branded.`); } - r += `</span>`; } if (V.abbreviateHormoneBalance === 1) { if (slave.hormoneBalance <= -21) { - r += `<span class="deepskyblue">`; - r += ` <strong>HB:M</strong>`; + makeSpan(para, "HB:M", ["deepskyblue", "strong"]); } else if (slave.hormoneBalance <= 20) { - r += `<span class="pink">`; - r += ` <strong>HB:N</strong>`; + makeSpan(para, "HB:N", ["pink", "strong"]); } else if (slave.hormoneBalance <= 500) { - r += `<span class="pink">`; - r += ` <strong>HB:F</strong>`; + makeSpan(para, "HB:F", ["pink", "strong"]); } - r += `</span>`; } else if (V.abbreviateHormoneBalance === 2) { - r += `<span class=`; - if (slave.hormoneBalance <= -21) { - r += `"deepskyblue"`; - } else { - r += `"pink"`; - } - r += `> `; + const colorClass = slave.hormoneBalance <= -21 ? "deepskyblue" : "pink"; + let desc = ""; if (slave.hormoneBalance < -400) { - r += `Overwhelmingly masculine`; + desc = `Overwhelmingly masculine`; } else if (slave.hormoneBalance <= -300) { - r += `Extremely masculine`; + desc = `Extremely masculine`; } else if (slave.hormoneBalance <= -200) { - r += `Heavily masculine`; + desc = `Heavily masculine`; } else if (slave.hormoneBalance <= -100) { - r += `Very masculine`; + desc = `Very masculine`; } else if (slave.hormoneBalance <= -21) { - r += `Masculine`; + desc = `Masculine`; } else if (slave.hormoneBalance <= 20) { - r += `Neutral`; + desc = `Neutral`; } else if (slave.hormoneBalance <= 99) { - r += `Feminine`; + desc = `Feminine`; } else if (slave.hormoneBalance <= 199) { - r += `Very feminine`; + desc = `Very feminine`; } else if (slave.hormoneBalance <= 299) { - r += `Heavily feminine`; + desc = `Heavily feminine`; } else if (slave.hormoneBalance <= 399) { - r += `Extremely feminine`; + desc = `Extremely feminine`; } else if (slave.hormoneBalance <= 500) { - r += `Overwhelmingly feminine`; + desc = `Overwhelmingly feminine`; } - r += ` hormone balance.</span>`; - } - r += "<br>"; - if (V.seeImages !== 1 || V.seeSummaryImages !== 1 || V.imageChoice === 1) { - r += " "; + makeSpan(para, desc + " hormone balance.", colorClass); } + + para = makeParagraph(res); + if (V.abbreviateSkills === 1) { - short_intelligence(slave); - short_sex_skills(slave); - if (slave.skill.combat > 0) { - r += "C"; - } - r += "</span> "; - short_prestige(slave); - short_porn_prestige(slave); + short_intelligence(slave, para); + short_skills(slave, para); + short_prestige(slave, para); + short_porn_prestige(slave, para); } else if (V.abbreviateSkills === 2) { - long_intelligence(slave); - long_sex_skills(slave); - if (slave.skill.combat > 0) { - r += "Trained fighter."; - } - r += "</span> "; - long_prestige(slave); - long_porn_prestige(slave); + long_intelligence(slave, para); + long_skills(slave, para); + long_prestige(slave, para); + long_porn_prestige(slave, para); } if (V.abbreviateMental === 1) { if (slave.fetish !== "mindbroken") { if (slave.fetishKnown === 1) { - short_fetish(slave); + short_fetish(slave, para); } if (slave.attrKnown === 1) { - short_attraction(slave); + short_attraction(slave, para); } } if (slave.clitPiercing === 3) { - short_smart_fetish(slave); - short_smart_attraction(slave); + short_smart_fetish(slave, para); + short_smart_attraction(slave, para); } - short_behavior_flaw(slave); - short_sex_flaw(slave); - short_behavior_quirk(slave); - short_sex_quirk(slave); + short_behavior_flaw(slave, para); + short_sex_flaw(slave, para); + short_behavior_quirk(slave, para); + short_sex_quirk(slave, para); } else if (V.abbreviateMental === 2) { if (slave.fetish !== "mindbroken") { if (slave.fetishKnown === 1) { - long_fetish(slave); + long_fetish(slave, para); } if (slave.attrKnown === 1) { - long_attraction(slave); + long_attraction(slave, para); } } if (slave.clitPiercing === 3) { - long_smart_fetish(slave); - long_smart_attraction(slave); + long_smart_fetish(slave, para); + long_smart_attraction(slave, para); } - long_behavior_flaw(slave); - long_sex_flaw(slave); - long_behavior_quirk(slave); - long_sex_quirk(slave); + long_behavior_flaw(slave, para); + long_sex_flaw(slave, para); + long_behavior_quirk(slave, para); + long_sex_quirk(slave, para); } if (slave.custom.label) { - r += `<strong><span class="yellow">${capFirstChar(slave.custom.label)}.</span></strong>`; + makeSpan(res, `${capFirstChar(slave.custom.label)}.`, ["yellow", "strong"]); } if ((slave.relationship !== 0) || (slave.relation !== 0) || (V.abbreviateClothes === 2) || (V.abbreviateRulesets === 2)) { - r += `<br>`; - if (V.seeImages !== 1 || V.seeSummaryImages !== 1 || V.imageChoice === 1) { - r += ` `; - } + para = makeParagraph(res); } if (V.abbreviateMental === 1) { - r += `<span class="lightgreen">`; - if (V.familyTesting === 1) { - short_extended_family(slave); - } else { - short_legacy_family(slave); - } - r += `</span>`; - short_clone(slave); - short_rival(slave); + makeSpan(para, V.familyTesting === 1 ? short_extended_family(slave) : short_legacy_family(slave), "lightgreen"); + short_clone(slave, para); + short_rival(slave, para); } else if (V.abbreviateMental === 2) { if (V.familyTesting === 1) { - long_extended_family(slave); + long_extended_family(slave, para); } else { - long_legacy_family(slave); + long_legacy_family(slave, para); } - long_clone(slave); - long_rival(slave); + long_clone(slave, para); + long_rival(slave, para); } if (slave.fuckdoll === 0) { if (V.abbreviateClothes === 2) { - r += ` `; + const dressingBlock = makeBlock(para); if (slave.choosesOwnClothes === 1) { - r += `Dressing ${getPronouns(slave).objectReflexive}. `; + makeSpan(dressingBlock, `Dressing ${getPronouns(slave).himself}.`); } - long_clothes(slave); - long_collar(slave); - long_belly(slave); + long_clothes(slave, dressingBlock); + long_collar(slave, dressingBlock); + long_belly(slave, dressingBlock); if (slave.missingArms !== 3) { - long_arms(slave); + long_arms(slave, dressingBlock); } if (slave.missingLegs !== 3) { - long_legs(slave); - long_shoes(slave); + long_legs(slave, dressingBlock); + long_shoes(slave, dressingBlock); } - long_chastity(slave); - long_vaginal_acc(slave); - long_dick_acc(slave); - long_buttplug(slave); + long_chastity(slave, dressingBlock); + long_vaginal_acc(slave, dressingBlock); + long_dick_acc(slave, dressingBlock); + long_buttplug(slave, dressingBlock); } } - r += ` `; - rules_assistant(slave); + const RABlock = makeBlock(para); + rules_assistant(slave, RABlock); if (V.abbreviateOrigins === 2 && slave.origin !== 0) { - origins(slave); + origins(slave, res); } - return r; + return res; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c */ - function short_devotion(slave) { + function short_devotion(slave, c) { if (slave.fetish === "mindbroken") { - r += `<span class="red">MB</span>`; + makeSpan(c, "MB", "red"); } else if (slave.devotion < -95) { - r += `<span class="darkviolet">Hate${V.summaryStats ? `[${slave.devotion}]` : ''}</span>`; + makeSpan(c, "Hate", "darkviolet", true, slave.devotion); } else if (slave.devotion < -50) { - r += `<span class="darkviolet">Hate${V.summaryStats ? `[${slave.devotion}]` : ''}</span>`; + makeSpan(c, "Hate", "darkviolet", true, slave.devotion); } else if (slave.devotion < -20) { - r += `<span class="mediumorchid">Res${V.summaryStats ? `[${slave.devotion}]` : ''}</span>`; + makeSpan(c, "Res", "mediumorchid", true, slave.devotion); } else if (slave.devotion <= 20) { - r += `<span class="yellow">Ambiv${V.summaryStats ? `[${slave.devotion}]` : ''}</span>`; + makeSpan(c, "Ambiv", "yellow", true, slave.devotion); } else if (slave.devotion <= 50) { - r += `<span class="hotpink">Accept${V.summaryStats ? `[${slave.devotion}]` : ''}</span>`; + makeSpan(c, "Accept", "hotpink", true, slave.devotion); } else if (slave.devotion <= 95) { - r += `<span class="deeppink">Devo${V.summaryStats ? `[${slave.devotion}]` : ''}</span>`; + makeSpan(c, "Devo", "deeppink", true, slave.devotion); } else { - r += `<span class="magenta">Wor${V.summaryStats ? `[${slave.devotion}]` : ''}</span>`; + makeSpan(c, "Wor", "magenta", true, slave.devotion); } - r += " "; if (slave.fetish === "mindbroken") { return; } else if (slave.trust < -95) { - r += `<span class="darkgoldenrod">ETerr${V.summaryStats ? `[${slave.trust}]` : ''}</span>`; + makeSpan(c, "ETerr", "darkgoldenrod", true, slave.trust); } else if (slave.trust < -50) { - r += `<span class="goldenrod">Terr${V.summaryStats ? `[${slave.trust}]` : ''}</span>`; + makeSpan(c, "Terr", "goldenrod", true, slave.trust); } else if (slave.trust < -20) { - r += `<span class="gold">Fright${V.summaryStats ? `[${slave.trust}]` : ''}</span>`; + makeSpan(c, "Fright", "gold", true, slave.trust); } else if (slave.trust <= 20) { - r += `<span class="yellow">Fear${V.summaryStats ? `[${slave.trust}]` : ''}</span>`; + makeSpan(c, "Fear", "yellow", true, slave.trust); } else if (slave.trust <= 50) { if (slave.devotion < -20) { - r += `<span class="orange">Caref${V.summaryStats ? `[${slave.trust}]` : ''}</span>`; + makeSpan(c, "Caref", "orange", true, slave.trust); } else { - r += `<span class="mediumaquamarine">Caref${V.summaryStats ? `[${slave.trust}]` : ''}</span>`; + makeSpan(c, "Caref", "mediumaquamarine", true, slave.trust); } } else if (slave.trust < 95) { if (slave.devotion < -20) { - r += `<span class="orangered">Bold${V.summaryStats ? `[${slave.trust}]` : ''}</span>`; + makeSpan(c, "Bold", "orangered", true, slave.trust); } else { - r += `<span class="mediumseagreen">Trust${V.summaryStats ? `[${slave.trust}]` : ''}</span>`; + makeSpan(c, "Trust", "mediumseagreen", true, slave.trust); } } else { if (slave.devotion < -20) { - r += `<span class="darkred">Defiant${V.summaryStats ? `[${slave.trust}]` : ''}</span>`; + makeSpan(c, "Defiant", "darkred", true, slave.trust); } else { - r += `<span class="seagreen">VTrust ${V.summaryStats ? `[${slave.trust}]` : ''}</span>`; + makeSpan(c, "VTrust", "seagreen", true, slave.trust); } } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_devotion(slave) { + function long_devotion(slave, c) { if (slave.fetish === "mindbroken") { - r += `<span class="red">Mindbroken.</span>`; + makeSpan(c, "Mindbroken.", "red"); } else if (slave.devotion < -95) { - r += `<span class="darkviolet">Very hateful${V.summaryStats ? `[${slave.devotion}]` : ''}.</span>`; + makeSpan(c, "Very hateful", "darkviolet", true, slave.devotion); } else if (slave.devotion < -50) { - r += `<span class="darkviolet">Hateful${V.summaryStats ? `[${slave.devotion}]` : ''}.</span>`; + makeSpan(c, "Hateful", "darkviolet", true, slave.devotion); } else if (slave.devotion < -20) { - r += `<span class="mediumorchid">Resistant${V.summaryStats ? `[${slave.devotion}]` : ''}.</span>`; + makeSpan(c, "Resistant", "mediumorchid", true, slave.devotion); } else if (slave.devotion <= 20) { - r += `<span class="yellow">Ambivalent${V.summaryStats ? `[${slave.devotion}]` : ''}.</span>`; + makeSpan(c, "Ambivalent", "yellow", true, slave.devotion); } else if (slave.devotion <= 50) { - r += `<span class="hotpink">Accepting${V.summaryStats ? `[${slave.devotion}]` : ''}.</span>`; + makeSpan(c, "Accepting", "hotpink", true, slave.devotion); } else if (slave.devotion <= 95) { - r += `<span class="deeppink">Devoted${V.summaryStats ? `[${slave.devotion}]` : ''}.</span>`; + makeSpan(c, "Devoted", "deeppink", true, slave.devotion); } else { - r += `<span class="magenta">Worshipful${V.summaryStats ? `[${slave.devotion}]` : ''}.</span>`; + makeSpan(c, "Worshipful", "magenta", true, slave.devotion); } - r += " "; if (slave.fetish === "mindbroken") { return; } else if (slave.trust < -95) { - r += `<span class="darkgoldenrod">Extremely terrified${V.summaryStats ? `[${slave.trust}]` : ''}.</span>`; + makeSpan(c, "Extremely terrified", "darkgoldenrod", true, slave.trust); } else if (slave.trust < -50) { - r += `<span class="goldenrod">Terrified${V.summaryStats ? `[${slave.trust}]` : ''}.</span>`; + makeSpan(c, "Terrified", "goldenrod", true, slave.trust); } else if (slave.trust < -20) { - r += `<span class="gold">Frightened${V.summaryStats ? `[${slave.trust}]` : ''}.</span>`; + makeSpan(c, "Frightened", "gold", true, slave.trust); } else if (slave.trust <= 20) { - r += `<span class="yellow">Fearful${V.summaryStats ? `[${slave.trust}]` : ''}.</span>`; + makeSpan(c, "Fearful", "yellow", true, slave.trust); } else if (slave.trust <= 50) { if (slave.devotion < -20) { - r += `<span class="orange">Careful${V.summaryStats ? `[${slave.trust}]` : ''}.</span>`; + makeSpan(c, "Careful", "orange", true, slave.trust); } else { - r += `<span class="mediumaquamarine">Careful${V.summaryStats ? `[${slave.trust}]` : ''}.</span>`; + makeSpan(c, "Careful", "mediumaquamarine", true, slave.trust); } } else if (slave.trust < 95) { if (slave.devotion < -20) { - r += `<span class="orangered">Bold${V.summaryStats ? `[${slave.trust}]` : ''}.</span>`; + makeSpan(c, "Bold", "orangered", true, slave.trust); } else { - r += `<span class="mediumseagreen">Trusting${V.summaryStats ? `[${slave.trust}]` : ''}.</span>`; + makeSpan(c, "Trusting", "mediumseagreen", true, slave.trust); } } else { if (slave.devotion < -20) { - r += `<span class="darkred">Defiant${V.summaryStats ? `[${slave.trust}]` : ''}.</span>`; + makeSpan(c, "Defiant", "darkred", true, slave.trust); } else { - r += `<span class="seagreen">Profoundly trusting${V.summaryStats ? `[${slave.trust}]` : ''}.</span>`; + makeSpan(c, "Profoundly trusting", "seagreen", true, slave.trust); } } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_rules(slave) { + function short_rules(slave, c) { + const tagName = "strong;" switch (slave.livingRules) { case "luxurious": - r += `<strong>LS:Lux</strong>`; + tag(c, tagName, "LS:Lux"); break; case "normal": - r += `<strong>LS:Nor</strong>`; + tag(c, tagName, "LS:Nor"); break; default: - r += `<strong>LS:Spa</strong>`; + tag(c, tagName, "LS:Spa"); break; } - r += " "; - if (canTalk(slave, false)) { + if (canTalk(slave)) { switch (slave.speechRules) { case "permissive": - r += `<strong>SpR:P</strong>`; + tag(c, tagName, "SpR:P"); break; case "accent elimination": - r += `<strong>SpR:NoAcc</strong>`; + tag(c, tagName, "SpR:NoAcc"); break; case "language lessons": - r += `<strong>SpR:LL</strong>`; + tag(c, tagName, "SpR:LL"); break; default: - r += `<strong>SpR:R</strong>`; + tag(c, tagName, "SpR:R"); break; } - r += " "; } switch (slave.relationshipRules) { case "permissive": - r += `<strong>ReR:P</strong>`; + tag(c, tagName, "ReR:P"); break; case "just friends": - r += `<strong>ReR:Fr</strong>`; + tag(c, tagName, "ReR:Fr"); break; default: - r += `<strong>ReR:R</strong>`; + tag(c, tagName, "ReR:R"); break; } - r += " "; switch (slave.standardPunishment) { case "confinement": - r += `<strong>Pun:Conf</strong>`; + tag(c, tagName, "Pun:Conf"); break; case "whipping": - r += `<strong>Pun:Whip</strong>`; + tag(c, tagName, "Pun:Whip"); break; case "chastity": - r += `<strong>Pun:Chas</strong>`; + tag(c, tagName, "Pun:Chas"); break; default: - r += `<strong>Pun:Situ</strong>`; + tag(c, tagName, "Pun:Situ"); break; } - r += " "; switch (slave.standardReward) { case "relaxation": - r += `<strong>Rew:Relx</strong>`; + tag(c, tagName, "Rew:Relx"); break; case "drugs": - r += `<strong>Rew:Drug</strong>`; + tag(c, tagName, "Rew:Drug"); break; case "orgasm": - r += `<strong>Rew:Orga</strong>`; + tag(c, tagName, "Rew:Orga"); break; default: - r += `<strong>Rew:Situ</strong>`; + tag(c, tagName, "Rew:Situ"); break; } - r += " "; switch (slave.releaseRules) { case "permissive": - r += `<strong>MaR:P</strong>`; + tag(c, tagName, "MaR:P"); break; case "sapphic": - r += `<strong>MaR:S</strong>`; + tag(c, tagName, "MaR:S"); break; case "masturbation": - r += `<strong>MaR:M</strong>`; + tag(c, tagName, "MaR:M"); break; case "chastity": - r += `<strong>MaR:C</strong>`; + tag(c, tagName, "MaR:C"); break; default: - r += `<strong>MaR:R</strong>`; + tag(c, tagName, "MaR:R"); break; } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_rules(slave) { - r += `Living standard: ${slave.livingRules}. `; - if (canTalk(slave, false)) { - r += `Speech rules: ${slave.speechRules}. `; - } - r += `Relationship rules: ${slave.relationshipRules}. `; - r += `Typical punishment: ${slave.standardPunishment}. `; - r += `Typical reward: ${slave.standardReward}. `; - r += `Release rules: ${slave.releaseRules}. `; + function long_rules(slave, c) { + addText(c, `Living standard: ${slave.livingRules}. `); + if (canTalk(slave)) { + addText(c, `Speech rules: ${slave.speechRules}. `); + } + addText(c, `Relationship rules: ${slave.relationshipRules}. `); + addText(c, `Typical punishment: ${slave.standardPunishment}. `); + addText(c, `Typical reward: ${slave.standardReward}. `); + addText(c, `Release rules: ${slave.releaseRules}. `); } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_weight(slave) { + function short_weight(slave, c) { if (slave.weight < -95) { - r += `<strong><span class="red">W---${V.summaryStats? `[${slave.weight}]` : ''}</span></strong>`; + makeSpan(c, "W---", ["red", "strong"], true, slave.weight); } else if (slave.weight < -30) { if (slave.hips < -1) { - r += `<strong>W--${V.summaryStats? `[${slave.weight}]` : ''}</strong>`; + makeSpan(c, "W--", "strong", true, slave.weight); } else { - r += `<strong><span class="red">W--${V.summaryStats? `[${slave.weight}]` : ''}</span></strong>`; + makeSpan(c, "W--", ["red", "strong>"], true, slave.weight); } } else if (slave.weight < -10) { - r += `<strong>W-${V.summaryStats? `[${slave.weight}]` : ''}</strong>`; + makeSpan(c, "W-", "strong", true, slave.weight); } else if (slave.weight <= 10) { - r += `<strong>W${V.summaryStats? `[${slave.weight}]` : ''}</strong>`; + makeSpan(c, "W", "strong", true, slave.weight); } else if (slave.weight <= 30) { - r += `<strong>W+${V.summaryStats? `[${slave.weight}]` : ''}</strong>`; + makeSpan(c, "W+", "strong", true, slave.weight); } else if (slave.weight <= 95) { if (slave.hips > 1 || V.arcologies[0].FSHedonisticDecadence !== "unset") { - r += `<strong>W++${V.summaryStats? `[${slave.weight}]` : ''}</strong>`; + makeSpan(c, "W++", "strong", true, slave.weight); } else { - r += `<strong><span class="red">W++${V.summaryStats? `[${slave.weight}]` : ''}</span></strong>`; + makeSpan(c, "W++", ["red", "strong"], true, slave.weight); } } else if (slave.weight <= 130) { if (slave.hips > 2 || V.arcologies[0].FSHedonisticDecadence !== "unset") { - r += `<strong>W+++${V.summaryStats? `[${slave.weight}]` : ''}</strong>`; + makeSpan(c, "W+++", "strong", true, slave.weight); } else { - r += `<strong><span class="red">W+++${V.summaryStats? `[${slave.weight}]` : ''}</span></strong>`; + makeSpan(c, "W+++", ["red", "strong"], true, slave.weight); } } else if (slave.weight <= 160) { if (V.arcologies[0].FSHedonisticDecadence !== "unset") { - r += `<strong>W++++${V.summaryStats? `[${slave.weight}]` : ''}</strong>`; + makeSpan(c, "W++++", "strong", true, slave.weight); } else { - r += `<strong><span class="red">W++++${V.summaryStats? `[${slave.weight}]` : ''}</span></strong>`; + makeSpan(c, "W++++", ["red", "strong"], true, slave.weight); } } else if (slave.weight <= 190) { if (V.arcologies[0].FSHedonisticDecadence !== "unset") { - r += `<strong>W+++++${V.summaryStats? `[${slave.weight}]` : ''}</strong>`; + makeSpan(c, "W+++++", "strong", true, slave.weight); } else { - r += `<strong><span class="red">W+++++${V.summaryStats? `[${slave.weight}]` : ''}</span></strong>`; + makeSpan(c, "W+++++", ["red", "strong"], true, slave.weight); } } else { if (V.arcologies[0].FSHedonisticDecadence !== "unset") { - r += `<strong>W++++++${V.summaryStats? `[${slave.weight}]` : ''}</strong>`; + makeSpan(c, "W++++++", "strong", true, slave.weight); } else { - r += `<strong><span class="red">W++++++${V.summaryStats? `[${slave.weight}]` : ''}</span></strong>`; + makeSpan(c, "W++++++", ["red", "strong"], true, slave.weight); } } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_weight(slave) { + function long_weight(slave, c) { if (slave.weight < -95) { - r += `<span class="red">Emaciated${V.summaryStats ? `[${slave.weight}]`: ''}.</span>`; + makeSpan(c, "Emaciated", "red", true, slave.weight); } else if (slave.weight < -30) { if (slave.hips < -1) { - r += `Model-thin${V.summaryStats? `[${slave.weight}]`: ''}.`; + makeSpan(c, "Model-thin", null, true, slave.weight); } else { - r += `<span class="red">Very thin${V.summaryStats ? `[${slave.weight}]`: ''}.</span>`; + makeSpan(c, "Very thin", "red", true, slave.weight); } } else if (slave.weight < -10) { - r += `Thin${V.summaryStats? `[${slave.weight}]`: ''}.`; + makeSpan(c, "Thin", null, true, slave.weight); } else if (slave.weight <= 10) { - r += `Trim${V.summaryStats? `[${slave.weight}]`: ''}.`; + makeSpan(c, "Trim", null, true, slave.weight); } else if (slave.weight <= 30) { - r += `Plush${V.summaryStats? `[${slave.weight}]`: ''}.`; + makeSpan(c, "Plush", null, true, slave.weight); } else if (slave.weight <= 95) { if (slave.hips > 1 || V.arcologies[0].FSHedonisticDecadence !== "unset") { - r += `Nicely chubby${V.summaryStats? `[${slave.weight}]`: ''}.`; + makeSpan(c, "Nicely chubby", null, true, slave.weight); } else { - r += `<span class="red">Overweight${V.summaryStats ? `[${slave.weight}]`: ''}.</span>`; + makeSpan(c, "Overweight", "red", true, slave.weight); } } else if (slave.weight <= 130) { if (slave.hips > 2 || V.arcologies[0].FSHedonisticDecadence !== "unset") { - r += `Pleasantly soft and shapely${V.summaryStats? `[${slave.weight}]`: ''}.`; + makeSpan(c, "Pleasantly soft and shapely", null, true, slave.weight); } else { - r += `<span class="red">Fat${V.summaryStats ? `[${slave.weight}]`: ''}.</span>`; + makeSpan(c, "Fat", "red", true, slave.weight); } } else if (slave.weight <= 160) { if (V.arcologies[0].FSHedonisticDecadence !== "unset") { - r += `Amazingly voluptuous${V.summaryStats? `[${slave.weight}]`: ''}.`; + makeSpan(c, "Amazingly voluptuous", null, true, slave.weight); } else { - r += `<span class="red">Obese${V.summaryStats ? `[${slave.weight}]`: ''}.</span>`; + makeSpan(c, "Obese", "red", true, slave.weight); } } else if (slave.weight <= 190) { if (V.arcologies[0].FSHedonisticDecadence !== "unset") { - r += `SSBBW${V.summaryStats? `[${slave.weight}]`: ''}.`; + makeSpan(c, "SSBBW", null, true, slave.weight); } else { - r += `<span class="red">Super Obese${V.summaryStats ? `[${slave.weight}]`: ''}.</span>`; + makeSpan(c, "Super Obese", "red", true, slave.weight); } } else { if (V.arcologies[0].FSHedonisticDecadence !== "unset") { - r += `Perfectly massive${V.summaryStats? `[${slave.weight}]`: ''}.`; + makeSpan(c, "Perfectly massive", null, true, slave.weight); } else { - r += `<span class="red">Dangerously Obese${V.summaryStats ? `[${slave.weight}]`: ''}.</span>`; + makeSpan(c, "Dangerously Obese", "red", true, slave.weight); } } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_diet(slave) { - r += `<span class="teal">`; + function short_diet(slave, c) { + let diet = makeSpan(null, "", ["teal", "strong"]); switch (slave.diet) { case "restricted": - r += `<strong>Di:W-</strong>`; + diet.textContent = "Di:W-"; break; case "fattening": - r += `<strong>Di:W+</strong>`; + diet.textContent = "Di:W+"; break; case "XX": - r += `<strong>Di:XX+</strong>`; + diet.textContent = "Di:XX+"; break; case "XY": - r += `<strong>Di:XY+</strong>`; + diet.textContent = "Di:XY+"; break; case "XXY": - r += `<strong>Di:XXY+</strong>`; + diet.textContent = "Di:XXY+"; break; case "muscle building": - r += `<strong>Di:M+</strong>`; + diet.textContent = "Di:M+"; break; case "slimming": - r += `<strong>Di:M-</strong>`; + diet.textContent = "Di:M-"; break; case "cum production": - r += `<strong>Di:C+</strong>`; + diet.textContent = "Di:C+"; break; case "cleansing": - r += `<strong>Di:H+</strong>`; + diet.textContent = "Di:H+"; break; case "fertility": - r += `<strong>Di:F+</strong>`; + diet.textContent = "Di:F+"; break; } - r += `</span> `; - r += `<span class="cyan">`; + if (diet.textContent.length > 0) { + c.appendChild(diet); + } + let specialDiet = makeSpan(null, "", ["cyan", "strong"]); if (slave.dietCum === 2) { - r += `<strong>Cum++</strong>`; + specialDiet.textContent = "Cum++"; } else if (((slave.dietCum === 1) && (slave.dietMilk === 0))) { - r += `<strong>Cum+</strong>`; + specialDiet.textContent = "Cum+"; } else if (((slave.dietCum === 1) && (slave.dietMilk === 1))) { - r += `<strong>Cum+ Milk+</strong>`; + specialDiet.textContent = "Cum+ Milk+"; } else if (((slave.dietCum === 0) && (slave.dietMilk === 1))) { - r += `<strong>Milk+</strong>`; + specialDiet.textContent = "Milk+"; } else if ((slave.dietMilk === 2)) { - r += `<strong>Milk++</strong>`; + specialDiet.textContent = ">Milk++"; + } + if (specialDiet.textContent.length > 0) { + c.appendChild(specialDiet); } - r += `</span> `; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_diet(slave) { - r += `<span class="teal">`; + function long_diet(slave, c) { + let dietDesc = ""; switch (slave.diet) { case "restricted": - r += `Dieting.`; + dietDesc = `Dieting.`; break; case "fattening": - r += `Gaining weight.`; + dietDesc = `Gaining weight.`; break; case "XX": - r += `Estrogen rich.`; + dietDesc = `Estrogen rich.`; break; case "XY": - r += `Testosterone rich.`; + dietDesc = `Testosterone rich.`; break; case "XXY": - r += `Futanari mix.`; + dietDesc = `Futanari mix.`; break; case "muscle building": - r += `Pumping iron.`; + dietDesc = `Pumping iron.`; break; case "slimming": - r += `Slimming down.`; + dietDesc = `Slimming down.`; break; case "cum production": - r += `Cum production.`; + dietDesc = `Cum production.`; break; case "cleansing": - r += `Cleansing.`; + dietDesc = `Cleansing.`; break; case "fertility": - r += `Fertility.`; + dietDesc = `Fertility.`; break; } - r += `</span> `; + + if (dietDesc) { + makeSpan(c, dietDesc, "teal"); + } + + function specialDiet(text) { + addText(c, "Diet base: "); + makeSpan(c, text, "cyan"); + } + if (slave.dietCum === 2) { - r += `Diet base: <span class="cyan">Cum Based.</span>`; + specialDiet("Cum Based."); } else if (((slave.dietCum === 1) && (slave.dietMilk === 0))) { - r += `Diet base: <span class="cyan">Cum Added.</span>`; + specialDiet("Cum Added."); } else if (((slave.dietCum === 1) && (slave.dietMilk === 1))) { - r += `Diet base: <span class="cyan">Milk & Cum Added.</span>`; + specialDiet("Milk & Cum Added."); } else if (((slave.dietCum === 0) && (slave.dietMilk === 1))) { - r += `Diet base: <span class="cyan">Milk Added.</span>`; + specialDiet("Milk Added."); } else if ((slave.dietMilk === 2)) { - r += `Diet base: <span class="cyan">Milk Based.</span>`; + specialDiet("Milk Based."); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_health(slave) { + function short_health(slave, c) { if (slave.health < -20) { - r += `<strong><span class="red">H${V.summaryStats? `[${slave.health}]` : ''}</span></strong>`; + makeSpan(c, "H", ["red", "strong"], true, slave.health); } else if (slave.health <= 20) { - r += `<strong><span class="yellow">H${V.summaryStats? `[${slave.health}]` : ''}</span></strong>`; + makeSpan(c, "H", ["yellow", "strong"], true, slave.health); } else if (slave.health > 20) { - r += `<strong><span class="green">H${V.summaryStats? `[${slave.health}]` : ''}</span></strong>`; + makeSpan(c, "H", ["green", "strong"], true, slave.health); } - r += " "; if (passage() === "Clinic" && V.clinicUpgradeScanner && slave.chem > 15) { - r += `<strong><span class="cyan">C${Math.ceil(slave.chem/10)}</span></strong> `; + makeSpan(c, `C${Math.ceil(slave.chem/10)}`, ["cyan", "strong"]); } } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_health(slave) { + function long_health(slave, c) { if (slave.health < -90) { - r += `<span class="red">On the edge of death${V.summaryStats? `[${slave.health}]` : ''}.</span>`; + makeSpan(c, "On the edge of death", ["red", "strong"], true, slave.health); } else if (slave.health < -50) { - r += `<span class="red">Extremely unhealthy${V.summaryStats? `[${slave.health}]` : ''}.</span>`; + makeSpan(c, "Extremely unhealthy", ["red", "strong"], true, slave.health); } else if (slave.health < -20) { - r += `<span class="red">Unhealthy${V.summaryStats? `[${slave.health}]` : ''}.</span>`; + makeSpan(c, "Unhealthy", ["red", "strong"], true, slave.health); } else if (slave.health <= 20) { - r += `<span class="yellow">Healthy${V.summaryStats? `[${slave.health}]` : ''}.</span>`; + makeSpan(c, "Healthy", "yellow", true, slave.health); } else if (slave.health <= 50) { - r += `<span class="green">Very healthy${V.summaryStats? `[${slave.health}]` : ''}.</span>`; + makeSpan(c, "Very healthy", "green", true, slave.health); } else if (slave.health <= 90) { - r += `<span class="green">Extremely healthy${V.summaryStats? `[${slave.health}]` : ''}.</span>`; + makeSpan(c, "Extremely healthy", "green", true, slave.health); } else { - r += `<span class="green">Unnaturally healthy${V.summaryStats? `[${slave.health}]` : ''}.</span>`; + makeSpan(c, "Unnaturally healthy", "green", true, slave.health); } - r += " "; if (passage() === "Clinic" && V.clinicUpgradeScanner && slave.chem > 15) { - r += `<strong><span class="cyan">Carcinogen buildup: ${Math.ceil(slave.chem/10)}</span>.</strong> `; + makeSpan(c, `Carcinogen buildup: ${Math.ceil(slave.chem/10)}.`, "cyan"); } } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_drugs(slave) { - r += `<span class="tan">`; + function short_drugs(slave, c) { + let drugDesc = ""; switch (slave.drugs) { case "breast injections": - r += `<strong>Dr:Boobs+</strong>`; + drugDesc = "Boobs+"; break; case "intensive breast injections": - r += `<strong>Dr:Boobs++</strong>`; + drugDesc = "Boobs++" break; case "hyper breast injections": - r += `<strong>Dr:Boobs+++</strong>`; + drugDesc = "Boobs+++" break; case "butt injections": - r += `<strong>Dr:Butt+</strong>`; + drugDesc = "Butt+"; break; case "intensive butt injections": - r += `<strong>Dr:Butt++</strong>`; + drugDesc = "Butt++"; break; case "hyper butt injections": - r += `<strong>Dr:Butt+++</strong>`; + drugDesc = "Butt+++"; break; case "lip injections": - r += `<strong>Dr:Lip+</strong>`; + drugDesc = "Lip+"; break; case "fertility drugs": - r += `<strong>Dr:Fert+</strong>`; + drugDesc = "Fert+"; break; case "super fertility drugs": - r += `<strong>Dr:Fert++</strong>`; + drugDesc = "Fert++"; break; case "penis enhancement": - r += `<strong>Dr:Dick+</strong>`; + drugDesc = "Dick+"; break; case "intensive penis enhancement": - r += `<strong>Dr:Dick++</strong>`; + drugDesc = "Dick++"; break; case "hyper penis enhancement": - r += `<strong>Dr:Dick+++</strong>`; + drugDesc = "Dick+++"; break; case "testicle enhancement": - r += `<strong>Dr:Balls+</strong>`; + drugDesc = "Balls+"; break; case "intensive testicle enhancement": - r += `<strong>Dr:Balls++</strong>`; + drugDesc = "Balls++"; break; case "hyper testicle enhancement": - r += `<strong>Dr:Balls+++</strong>`; + drugDesc = "Balls+++"; break; case "psychosuppressants": - r += `<strong>Dr:Psych</strong>`; + drugDesc = "Psych"; break; case "steroids": - r += `<strong>Dr:Ster</strong>`; + drugDesc = "Ster"; break; case "female hormone injections": - r += `<strong>Dr:HormXX++</strong>`; + drugDesc = "HormXX++"; break; case "male hormone injections": - r += `<strong>Dr:HormXY++</strong>`; + drugDesc = "HormXY++"; break; case "hormone enhancers": - r += `<strong>Dr:Horm+</strong>`; + drugDesc = "Horm+"; break; case "hormone blockers": - r += `<strong>Dr:Horm-</strong>`; + drugDesc = "Horm-"; break; case "anti-aging cream": - r += `<strong>Dr:Age-</strong>`; + drugDesc = "Age-"; break; case "appetite suppressors": - r += `<strong>Dr:ApSup</strong>`; + drugDesc = "ApSup"; break; case "penis atrophiers": - r += `<strong>Dr:Dick-</strong>`; + drugDesc = "Dick-"; break; case "testicle atrophiers": - r += `<strong>Dr:Balls-</strong>`; + drugDesc = "Balls-"; break; case "clitoris atrophiers": - r += `<strong>Dr:Clit-</strong>`; + drugDesc = "Clit-"; break; case "labia atrophiers": - r += `<strong>Dr:Labia-</strong>`; + drugDesc = "Labia-"; break; case "nipple atrophiers": - r += `<strong>Dr:Nipple-</strong>`; + drugDesc = "Nipple-"; break; case "lip atrophiers": - r += `<strong>Dr:Lip-</strong>`; + drugDesc = "Lip-"; break; case "breast redistributors": - r += `<strong>Dr:Breast-</strong>`; + drugDesc = "Breast-"; break; case "butt redistributors": - r += `<strong>Dr:Butt-</strong>`; + drugDesc = "Butt-"; break; case "sag-B-gone": - r += `<strong>Dr:AntiSag</strong>`; + drugDesc = "AntiSag"; break; case "growth stimulants": - r += `<strong>Dr:GroStim</strong>`; + drugDesc = "GroStim"; break; case "priapism agents": - r += `<strong>Dr:Erection</strong>`; + drugDesc = "Erection"; break; } - r += `</span> `; - r += `<span class="lightgreen">`; + if (drugDesc) { + makeSpan(c, "Dr:" + drugDesc, ["tan", "strong"]); + } if (slave.curatives === 2) { - r += `<strong>Cura</strong>`; + makeSpan(c, "Cura", ["lightgreen", "strong"]); } else if (slave.curatives === 1) { - r += `<strong>Prev</strong>`; + makeSpan(c, "Prev", ["lightgreen", "strong"]); } - r += `</span> `; if (slave.aphrodisiacs !== 0) { - r += `<span class="lightblue">`; if (slave.aphrodisiacs === 1) { - r += `<strong>Aph</strong>`; + makeSpan(c, "Aph", ["lightblue", "strong"]); } else if (slave.aphrodisiacs === 2) { - r += `<strong>Aph++</strong>`; + makeSpan(c, "Aph++", ["lightblue", "strong"]); } else { - r += `<strong>Anaph</strong>`; + makeSpan(c, "Anaph", ["lightblue", "strong"]); } - r += `</span> `; } if (slave.addict !== 0) { - r += `<span class="cyan">Add</span>`; + makeSpan(c, "Add", "cyan"); } - r += `<span class="lightsalmon">`; + let styles = ["lightsalmon", "strong"]; if (slave.hormones > 1) { - r += `<strong>Ho:F+</strong>`; + makeSpan(c, "Ho:F+", styles); } else if (slave.hormones > 0) { - r += `<strong>Ho:F</strong>`; + makeSpan(c, "Ho:F", styles); } else if (slave.hormones < -1) { - r += `<strong>Ho:M+</strong>`; + makeSpan(c, "Ho:M+", styles, ); } else if (slave.hormones < 0) { - r += `<strong>Ho:M</strong>`; + makeSpan(c, "Ho:M", styles); } - r += `</span> `; - r += `<span class="mediumseagreen">`; + + styles = ["mediumseagreen", "strong"]; if ((slave.bellyImplant > -1)) { - r += `<strong>Belly Imp</strong>`; + makeSpan(c, "Belly Imp", styles); } else if (((slave.preg <= -2) || (slave.ovaries === 0)) && (slave.vagina !== -1)) { - r += `<strong>Barr</strong>`; + makeSpan(c, "Barr", styles); } else if (slave.pubertyXX === 0 && (slave.ovaries === 1 || slave.mpreg === 1)) { - r += `<strong>Prepub</strong>`; + makeSpan(c, "Prepub", styles); } else if (slave.ovaryAge >= 47 && (slave.ovaries === 1 || slave.mpreg === 1)) { - r += `<strong>Meno</strong>`; + makeSpan(c, "Meno", styles); } else if (slave.pregWeek < 0) { - r += `<strong>Postpartum</strong>`; + makeSpan(c, "Postpartum", styles); } else if (slave.preg === -1) { - r += `<strong>CC</strong>`; + makeSpan(c, "CC", styles); } else if (slave.preg === 0 && (slave.ovaries === 1 || slave.mpreg === 1)) { - r += `<strong>Fert+</strong>`; + makeSpan(c, "Fert+", styles); } else if (((slave.preg < slave.pregData.normalBirth / 10) && (slave.preg > 0) && slave.pregKnown === 0) || slave.pregWeek === 1) { - r += `<strong>Preg?</strong>`; + makeSpan(c, "Preg?", styles); } else if ((slave.preg >= 36) && (slave.broodmother > 0)) { - r += `<strong>Perm preg</strong>`; + makeSpan(c, "Perm preg", styles); } else if (slave.pregKnown === 1) { - r += `<strong>${slave.pregWeek} wks preg</strong>`; + makeSpan(c, `${slave.pregWeek} wks preg`, styles); } - r += `</span> `; if (slave.induce === 1) { - r += `<span class="orange"><strong>Early Labor</strong></span>`; + makeSpan(c, "Early Labor", ["orange", "strong"]); } if (slave.pubertyXY === 0 && slave.balls > 0) { - r += `<strong>Prepub balls</strong>`; + makeSpan(c, "Prepub balls", "strong"); } if (slave.balls > 0 && slave.vasectomy === 1) { - r += `<strong>Vasect</strong>`; + makeSpan(c, "Vasect", "strong"); } - r += `<span class="springgreen">`; + styles = ["springgreen", "strong"]; if (slave.inflation === 3) { - r += `<strong>8 ltr ${slave.inflationType}</strong>`; + makeSpan(c, `8 ltr ${slave.inflationType}`, styles); } else if (slave.inflation === 2) { - r += `<strong>4 ltr ${slave.inflationType}</strong>`; + makeSpan(c, `4 ltr ${slave.inflationType}`, styles); } else if (slave.inflation === 1) { - r += `<strong>2 ltr ${slave.inflationType}</strong>`; + makeSpan(c, `2 ltr ${slave.inflationType}`, styles); } else if (slave.bellyFluid > 0) { - r += `<strong>${slave.bellyFluid}ccs ${slave.inflationType}</strong>`; + makeSpan(c, `${slave.bellyFluid}ccs ${slave.inflationType}`, styles); } - r += `</span> `; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_drugs(slave) { + function long_drugs(slave, c) { let swd = WombGetLittersData(slave); if ((slave.drugs !== "no drugs") && (slave.drugs !== "none")) { - r += `<span class="tan">On ${slave.drugs}.</span> `; + makeSpan(c, `On ${slave.drugs}.`, "tan"); } - r += `<span class="lightgreen">`; if (slave.curatives === 2) { - r += `On curatives.`; + makeSpan(c, "On curatives.", "lightgreen"); } else if (slave.curatives === 1) { - r += `On preventatives.`; + makeSpan(c, "On preventatives.", "lightgreen"); } - r += `</span> `; - r += `<span class="lightblue">`; if (slave.aphrodisiacs > 0) { - r += `On ${slave.aphrodisiacs > 1 ? 'extreme': ''} aphrodisiacs.`; + makeSpan(c, `On ${slave.aphrodisiacs > 1 ? 'extreme' : ''} aphrodisiacs.`, "lightblue"); } else if (slave.aphrodisiacs === -1) { - r += `On anaphrodisiacs.`; + makeSpan(c, "On anaphrodisiacs.", "lightblue"); } - r += `</span> `; if (slave.addict !== 0) { - r += `<span class="cyan">Addict.</span>`; + makeSpan(c, "Addict.", "cyan"); } - r += `<span class="lightsalmon">`; if (slave.hormones > 1) { - r += `Heavy female hormones.`; + makeSpan(c, "Heavy female hormones.", "lightsalmon"); } else if (slave.hormones > 0) { - r += `Female hormones.`; + makeSpan(c, "Female hormones.", "lightsalmon"); } else if (slave.hormones < -1) { - r += `Heavy male hormones.`; + makeSpan(c, "Heavy male hormones.", "lightsalmon"); } else if (slave.hormones < 0) { - r += `Male hormones.`; + makeSpan(c, "Male hormones.", "lightsalmon"); } - r += `</span> `; - r += `<span class="mediumseagreen">`; + let styles = "mediumseagreen"; if ((slave.bellyImplant > -1)) { - r += `Belly Implant.`; + makeSpan(c, "Belly Implant.", styles); } else if (((slave.preg <= -2) || (slave.ovaries === 0)) && (slave.vagina !== -1)) { - r += `Barren.`; + makeSpan(c, "Barren.", styles); } else if (slave.pubertyXX === 0 && (slave.ovaries === 1 || slave.mpreg === 1)) { - r += `Not ovulating yet.`; + makeSpan(c, "Not ovulating yet.", styles); } else if (slave.ovaryAge >= 47 && (slave.ovaries === 1 || slave.mpreg === 1)) { - r += `Menopausal.`; + makeSpan(c, "Menopausal.", styles); } else if (slave.pregWeek < 0) { - r += `Postpartum.`; + makeSpan(c, "Postpartum.", styles); } else if (slave.preg === -1) { - r += `On contraceptives.`; + makeSpan(c, "On contraceptives.", styles); } else if (slave.preg === 0 && (slave.ovaries === 1 || slave.mpreg === 1)) { - r += `Fertile.`; + makeSpan(c, "Fertile.", styles); } else if ((slave.preg >= 36) && (slave.broodmother > 0)) { - r += `Permanently pregnant.`; + makeSpan(c, "Permanently pregnant.", styles); } else if (swd.litters.length > 1) { - r += `<span class="lime">`; - r += `Concurrent pregnancies: (${swd.litters.length} sets).`; - r+= ` Max:${swd.litters[0]} / Min:${swd.litters[swd.litters.length-1]} week(s).`; - r += `</span> `; + let pregTxt = `Concurrent pregnancies: (${swd.litters.length} sets).`; + pregTxt += ` Max:${swd.litters[0]} / Min:${swd.litters[swd.litters.length-1]} week(s).`; + makeSpan(c, pregTxt, "lime"); } else if (((slave.preg < slave.pregData.normalBirth / 10) && (slave.preg > 0) && slave.pregKnown === 0) || slave.pregWeek === 1) { - r += `May be pregnant.`; + makeSpan(c, "May be pregnant."); } else if (slave.pregKnown === 1) { if (slave.pregType < 2 || slave.broodmother > 0) { - r += `${slave.pregWeek} weeks pregnant.`; + makeSpan(c, `${slave.pregWeek} weeks pregnant.`); } else { - r += `${slave.pregWeek} weeks pregnant with `; + let desc = `${slave.pregWeek} weeks pregnant with `; if (slave.pregType >= 40) { - r += `a tremendous brood of offspring.`; + desc += `a tremendous brood of offspring.`; } else if (slave.pregType >= 20) { - r += `a brood of offspring.`; + desc += `a brood of offspring.`; } else if (slave.pregType >= 10) { - r += `${slave.pregType} babies.`; + desc += `${slave.pregType} babies.`; } else if (slave.pregType === 9) { - r += `nonuplets.`; + desc += `nonuplets.`; } else if (slave.pregType === 8) { - r += `octuplets.`; + desc += `octuplets.`; } else if (slave.pregType === 7) { - r += `septuplets.`; + desc += `septuplets.`; } else if (slave.pregType === 6) { - r += `sextuplets.`; + desc += `sextuplets.`; } else if (slave.pregType === 5) { - r += `quintuplets.`; + desc += `quintuplets.`; } else if (slave.pregType === 4) { - r += `quadruplets.`; + desc += `quadruplets.`; } else if (slave.pregType === 3) { - r += `triplets.`; + desc += `triplets.`; } else { - r += `twins.`; + desc += `twins.`; } + makeSpan(c, desc); } if (slave.preg > slave.pregData.normalBirth && slave.broodmother === 0) { - r += ` (Overdue.)`; + makeSpan(c, "(Overdue.)"); } } - r += `</span> `; if (slave.induce === 1) { - r += `<span class="orange">Showing signs of early labor.</span>`; + makeSpan(c, "Showing signs of early labor.", "orange"); } if (slave.pubertyXY === 0 && slave.balls > 0) { - r += `Has not had first ejaculation.`; + makeSpan(c, "Has not had first ejaculation."); } if (slave.balls > 0 && slave.vasectomy === 1) { - r += `Vasectomy.`; + makeSpan(c, "Vasectomy."); } - r += `<span class="springgreen">`; if (slave.inflation === 3) { - r += `Filled with 8 liters of ${slave.inflationType}.`; + makeSpan(c, `Filled with 8 liters of ${slave.inflationType}.`, "springgreen"); } else if (slave.inflation === 2) { - r += `Filled with 4 liters of ${slave.inflationType}.`; + makeSpan(c, `Filled with 4 liters of ${slave.inflationType}.`, "springgreen"); } else if (slave.inflation === 1) { - r += `Filled with 2 liters of ${slave.inflationType}.`; + makeSpan(c, `Filled with 2 liters of ${slave.inflationType}.`, "springgreen"); } else if (slave.bellyFluid > 0) { - r += `Stuffed with ${slave.bellyFluid}ccs of ${slave.inflationType}.`; + makeSpan(c, `Stuffed with ${slave.bellyFluid}ccs of ${slave.inflationType}.`, "springgreen"); } - r += `</span> `; } /** * @param {App.Entity.SlaveState} slave + * @returns {string} */ function long_race(slave) { switch (slave.race) { case "white": - r += `Caucasian.`; - break; + return `Caucasian.`; case "asian": - r += `Asian.`; - break; + return `Asian.`; case "indo-aryan": - r += `Indo-aryan.`; - break; + return `Indo-aryan.`; case "latina": - r += `Latina.`; - break; + return `Latina.`; case "middle eastern": - r += `Middle Eastern.`; - break; + return `Middle Eastern.`; case "black": - r += `Black.`; - break; + return `Black.`; case "pacific islander": - r += `Pacific Islander.`; - break; + return `Pacific Islander.`; case "malay": - r += `Malay.`; - break; + return `Malay.`; case "amerindian": - r += `Amerindian.`; - break; + return `Amerindian.`; case "semitic": - r += `Semitic.`; - break; + return `Semitic.`; case "southern european": - r += `Southern European.`; - break; + return `Southern European.`; case "mixed race": - r += `Mixed race.`; - break; + return `Mixed race.`; default: - r += `${slave.race.charAt(0).toUpperCase() + slave.race.slice(1)}.`; - break; + return `${slave.race.charAt(0).toUpperCase() + slave.race.slice(1)}.`; } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @returns {string} */ function short_race(slave) { switch (slave.race) { case "white": - r += `C`; - break; + return `C`; case "asian": - r += `A`; - break; + return `A`; case "indo-aryan": - r += `I`; - break; + return `I`; case "latina": - r += `L`; - break; + return `L`; case "middle eastern": - r += `ME`; - break; + return `ME`; case "black": - r += `B`; - break; + return `B`; case "pacific islander": - r += `PI`; - break; + return `PI`; case "malay": - r += `M`; - break; + return `M`; case "amerindian": - r += `AI`; - break; + return `AI`; case "semitic": - r += `S`; - break; + return `S`; case "southern european": - r += `SE`; - break; + return `SE`; case "mixed race": - r += `MR`; - break; + return `MR`; default: - r += `${slave.race.charAt(0).toUpperCase() + slave.race.charAt(1) + slave.race.charAt(2)}`; - break; + return `${slave.race.charAt(0).toUpperCase() + slave.race.charAt(1) + slave.race.charAt(2)}`; } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @returns {string} */ function short_nationality(slave) { - r += `<span class="tan">`; switch (slave.nationality) { case "Afghan": - r += `Afg`; - break; + return "Afg"; case "Albanian": - r += `Alb`; - break; + return "Alb"; case "Algerian": - r += `Alg`; - break; + return "Alg"; case "American": - r += `USA`; - break; + return "USA"; case "Andorran": - r += `And`; - break; + return "And"; case "Angolan": - r += `Ang`; - break; + return "Ang"; case "Antiguan": - r += `AB`; - break; + return "AB"; case "Argentinian": - r += `Arg`; - break; + return "Arg"; case "Armenian": - r += `Arm`; - break; + return "Arm"; case "Aruban": - r += `Aru`; - break; + return "Aru"; case "Australian": - r += `Aus`; - break; + return "Aus"; case "Austrian": - r += `Aut`; - break; + return "Aut"; case "Azerbaijani": - r += `Aze`; - break; + return "Aze"; case "Bahamian": - r += `Bah`; - break; + return "Bah"; case "Bahraini": - r += `Bah`; - break; + return "Bah"; case "Bangladeshi": - r += `Bgd`; - break; + return "Bgd"; case "Barbadian": - r += `Bar`; - break; + return "Bar"; case "Belarusian": - r += `Ber`; - break; + return "Ber"; case "Belgian": - r += `Bel`; - break; + return "Bel"; case "Belizean": - r += `Blz`; - break; + return "Blz"; case "Beninese": - r += `Ben`; - break; + return "Ben"; case "Bermudian": - r += `Bmd`; - break; + return "Bmd"; case "Bhutanese": - r += `Bhu`; - break; + return "Bhu"; case "Bissau-Guinean": - r += `GB`; - break; + return "GB"; case "Bolivian": - r += `Bol`; - break; + return "Bol"; case "Bosnian": - r += `Bos`; - break; + return "Bos"; case "Brazilian": - r += `Bra`; - break; + return "Bra"; case "British": - r += `UK`; - break; + return "UK"; case "Bruneian": - r += `Bru`; - break; + return "Bru"; case "Bulgarian": - r += `Bul`; - break; + return "Bul"; case "Burkinabé": - r += `BF`; - break; + return "BF"; case "Burmese": - r += `Bur`; - break; + return "Bur"; case "Burundian": - r += `Bnd`; - break; + return "Bnd"; case "Cambodian": - r += `Kam`; - break; + return "Kam"; case "Cameroonian": - r += `Cam`; - break; + return "Cam"; case "Canadian": - r += `Can`; - break; + return "Can"; case "Cape Verdean": - r += `CV`; - break; + return "CV"; case "Catalan": - r += `Cat`; - break; + return "Cat"; case "Central African": - r += `CAR`; - break; + return "CAR"; case "Chadian": - r += `Cha`; - break; + return "Cha"; case "Chilean": - r += `Chl`; - break; + return "Chl"; case "Chinese": - r += `Chi`; - break; + return "Chi"; case "Colombian": - r += `Col`; - break; + return "Col"; case "Comorian": - r += `Com`; - break; + return "Com"; case "Congolese": - r += `RC`; - break; + return "RC"; case "a Cook Islander": - r += `CI`; - break; + return "CI"; case "Costa Rican": - r += `CR`; - break; + return "CR"; case "Croatian": - r += `Cro`; - break; + return "Cro"; case "Cuban": - r += `Cub`; - break; + return "Cub"; case "Curaçaoan": - r += `Cur`; - break; + return "Cur"; case "Cypriot": - r += `Cyp`; - break; + return "Cyp"; case "Czech": - r += `Cze`; - break; + return "Cze"; case "Danish": - r += `Den`; - break; + return "Den"; case "Djiboutian": - r += `Dji`; - break; + return "Dji"; case "Dominican": - r += `DR`; - break; + return "DR"; case "Dominiquais": - r += `Dom`; - break; + return "Dom"; case "Dutch": - r += `Nld`; - break; + return "Nld"; case "East Timorese": - r += `ET`; - break; + return "ET"; case "Ecuadorian": - r += `Ecu`; - break; + return "Ecu"; case "Egyptian": - r += `Egy`; - break; + return "Egy"; case "Emirati": - r += `UAE`; - break; + return "UAE"; case "Equatoguinean": - r += `EG`; - break; + return "EG"; case "Eritrean": - r += `Eri`; - break; + return "Eri"; case "Estonian": - r += `Est`; - break; + return "Est"; case "Ethiopian": - r += `Eth`; - break; + return "Eth"; case "Fijian": - r += `Fij`; - break; + return "Fij"; case "Filipina": - r += `Phl`; - break; + return "Phl"; case "Finnish": - r += `Fin`; - break; + return "Fin"; case "French": - r += `Fra`; - break; + return "Fra"; case "French Guianan": - r += `FG`; - break; + return "FG"; case "French Polynesian": - r += `FP`; - break; + return "FP"; case "Gabonese": - r += `Gab`; - break; + return "Gab"; case "Gambian": - r += `Gam`; - break; + return "Gam"; case "Georgian": - r += `Geo`; - break; + return "Geo"; case "German": - r += `Ger`; - break; + return "Ger"; case "Ghanan": - r += `Gha`; - break; + return "Gha"; case "Greek": - r += `Gre`; - break; + return "Gre"; case "Greenlandic": - r += `Grn`; - break; + return "Grn"; case "Grenadian": - r += `Gda`; - break; + return "Gda"; case "Guamanian": - r += `Gua`; - break; + return "Gua"; case "Guatemalan": - r += `Gtm`; - break; + return "Gtm"; case "Guinean": - r += `Gui`; - break; + return "Gui"; case "Guyanese": - r += `Guy`; - break; + return "Guy"; case "Haitian": - r += `Hai`; - break; + return "Hai"; case "Honduran": - r += `Hon`; - break; + return "Hon"; case "Hungarian": - r += `Hun`; - break; + return "Hun"; case "I-Kiribati": - r += `Kir`; - break; + return "Kir"; case "Icelandic": - r += `Ice`; - break; + return "Ice"; case "Indian": - r += `Ind`; - break; + return "Ind"; case "Indonesian": - r += `Idn`; - break; + return "Idn"; case "Iranian": - r += `Irn`; - break; + return "Irn"; case "Iraqi": - r += `Irq`; - break; + return "Irq"; case "Irish": - r += `Irl`; - break; + return "Irl"; case "Israeli": - r += `Isr`; - break; + return "Isr"; case "Italian": - r += `Ita`; - break; + return "Ita"; case "Ivorian": - r += `IC`; - break; + return "IC"; case "Jamaican": - r += `Jam`; - break; + return "Jam"; case "Japanese": - r += `Jpn`; - break; + return "Jpn"; case "Jordanian": - r += `Jor`; - break; + return "Jor"; case "Kazakh": - r += `Kaz`; - break; + return "Kaz"; case "Kenyan": - r += `Ken`; - break; + return "Ken"; case "Kittitian": - r += `SKN`; - break; + return "SKN"; case "Korean": - r += `Kor`; - break; + return "Kor"; case "Kosovan": - r += `Kos`; - break; + return "Kos"; case "Kurdish": - r += `Kur`; - break; + return "Kur"; case "Kuwaiti": - r += `Kuw`; - break; + return "Kuw"; case "Kyrgyz": - r += `Kyr`; - break; + return "Kyr"; case "Laotian": - r += `Lao`; - break; + return "Lao"; case "Latvian": - r += `Lat`; - break; + return "Lat"; case "Lebanese": - r += `Lbn`; - break; + return "Lbn"; case "Liberian": - r += `Lib`; - break; + return "Lib"; case "Libyan": - r += `Lby`; - break; + return "Lby"; case "a Liechtensteiner": - r += `Lie`; - break; + return "Lie"; case "Lithuanian": - r += `Lit`; - break; + return "Lit"; case "Luxembourgian": - r += `Lux`; - break; + return "Lux"; case "Macedonian": - r += `Mac`; - break; + return "Mac"; case "Malagasy": - r += `Mad`; - break; + return "Mad"; case "Malawian": - r += `Mwi`; - break; + return "Mwi"; case "Malaysian": - r += `Mys`; - break; + return "Mys"; case "Maldivian": - r += `Mdv`; - break; + return "Mdv"; case "Malian": - r += `Mal`; - break; + return "Mal"; case "Maltese": - r += `Mlt`; - break; + return "Mlt"; case "Marshallese": - r += `MI`; - break; + return "MI"; case "Mauritanian": - r += `Mta`; - break; + return "Mta"; case "Mauritian": - r += `Mts`; - break; + return "Mts"; case "Mexican": - r += `Mex`; - break; + return "Mex"; case "Micronesian": - r += `FSM`; - break; + return "FSM"; case "Moldovan": - r += `Mol`; - break; + return "Mol"; case "Monégasque": - r += `Mnc`; - break; + return "Mnc"; case "Mongolian": - r += `Mon`; - break; + return "Mon"; case "Montenegrin": - r += `Mng`; - break; + return "Mng"; case "Moroccan": - r += `Mor`; - break; + return "Mor"; case "Mosotho": - r += `Les`; - break; + return "Les"; case "Motswana": - r += `Bot`; - break; + return "Bot"; case "Mozambican": - r += `Moz`; - break; + return "Moz"; case "Namibian": - r += `Nam`; - break; + return "Nam"; case "Nauruan": - r += `Nau`; - break; + return "Nau"; case "Nepalese": - r += `Npl`; - break; + return "Npl"; case "New Caledonian": - r += `NC`; - break; + return "NC"; case "a New Zealander": - r += `NZ`; - break; + return "NZ"; case "Ni-Vanuatu": - r += `Van`; - break; + return "Van"; case "Nicaraguan": - r += `Nic`; - break; + return "Nic"; case "Nigerian": - r += `Nga`; - break; + return "Nga"; case "Nigerien": - r += `Ngr`; - break; + return "Ngr"; case "Niuean": - r += `Niu`; - break; + return "Niu"; case "Norwegian": - r += `Nor`; - break; + return "Nor"; case "Omani": - r += `Omn`; - break; + return "Omn"; case "Pakistani": - r += `Pak`; - break; + return "Pak"; case "Palauan": - r += `Plu`; - break; + return "Plu"; case "Palestinian": - r += `Pal`; - break; + return "Pal"; case "Panamanian": - r += `Pan`; - break; + return "Pan"; case "Papua New Guinean": - r += `PNG`; - break; + return "PNG"; case "Paraguayan": - r += `Par`; - break; + return "Par"; case "Peruvian": - r += `Per`; - break; + return "Per"; case "Polish": - r += `Pol`; - break; + return "Pol"; case "Portuguese": - r += `Por`; - break; + return "Por"; case "Puerto Rican": - r += `PR`; - break; + return "PR"; case "Qatari": - r += `Qat`; - break; + return "Qat"; case "Romanian": - r += `Rom`; - break; + return "Rom"; case "Russian": - r += `Rus`; - break; + return "Rus"; case "Rwandan": - r += `Rwa`; - break; + return "Rwa"; case "Sahrawi": - r += `Sah`; - break; + return "Sah"; case "Saint Lucian": - r += `SL`; - break; + return "SL"; case "Salvadoran": - r += `ES`; - break; + return "ES"; case "Sammarinese": - r += `SM`; - break; + return "SM"; case "Samoan": - r += `Sam`; - break; + return "Sam"; case "São Toméan": - r += `STP`; - break; + return "STP"; case "Saudi": - r += `Sau`; - break; + return "Sau"; case "Scottish": - r += `Sco`; - break; + return "Sco"; case "Senegalese": - r += `Sen`; - break; + return "Sen"; case "Serbian": - r += `Srb`; - break; + return "Srb"; case "Seychellois": - r += `Sey`; - break; + return "Sey"; case "Sierra Leonean": - r += `Sie`; - break; + return "Sie"; case "Singaporean": - r += `Sng`; - break; + return "Sng"; case "Slovak": - r += `Svk`; - break; + return "Svk"; case "Slovene": - r += `Svn`; - break; + return "Svn"; case "a Solomon Islander": - r += `SI`; - break; + return "SI"; case "Somali": - r += `Som`; - break; + return "Som"; case "South African": - r += `RSA`; - break; + return "RSA"; case "South Sudanese": - r += `SS`; - break; + return "SS"; case "Spanish": - r += `Spa`; - break; + return "Spa"; case "Sri Lankan": - r += `Sri`; - break; + return "Sri"; case "Sudanese": - r += `Sud`; - break; + return "Sud"; case "Surinamese": - r += `Sur`; - break; + return "Sur"; case "Swazi": - r += `Swa`; - break; + return "Swa"; case "Swedish": - r += `Swe`; - break; + return "Swe"; case "Swiss": - r += `Swi`; - break; + return "Swi"; case "Syrian": - r += `Syr`; - break; + return "Syr"; case "Taiwanese": - r += `Tai`; - break; + return "Tai"; case "Tajik": - r += `Taj`; - break; + return "Taj"; case "Tanzanian": - r += `Tza`; - break; + return "Tza"; case "Thai": - r += `Tha`; - break; + return "Tha"; case "Tibetan": - r += `Tib`; - break; + return "Tib"; case "Togolese": - r += `Tog`; - break; + return "Tog"; case "Tongan": - r += `Ton`; - break; + return "Ton"; case "Trinidadian": - r += `TT`; - break; + return "TT"; case "Tunisian": - r += `Tun`; - break; + return "Tun"; case "Turkish": - r += `Tur`; - break; + return "Tur"; case "Turkmen": - r += `Tkm`; - break; + return "Tkm"; case "Tuvaluan": - r += `Tuv`; - break; + return "Tuv"; case "Ugandan": - r += `Uga`; - break; + return "Uga"; case "Ukrainian": - r += `Ukr`; - break; + return "Ukr"; case "Uruguayan": - r += `Uru`; - break; + return "Uru"; case "Uzbek": - r += `Uzb`; - break; + return "Uzb"; case "Vatican": - r += `VC`; - break; + return "VC"; case "Venezuelan": - r += `Ven`; - break; + return "Ven"; case "Vietnamese": - r += `Vnm`; - break; + return "Vnm"; case "Vincentian": - r += `SVG`; - break; + return "SVG"; case "Yemeni": - r += `Yem`; - break; + return "Yem"; case "Zairian": - r += `DRC`; - break; + return "DRC"; case "Zambian": - r += `Zam`; - break; + return "Zam"; case "Zimbabwean": if (slave.race === "white") { - r += `Rho`; + return `Rho`; } else { - r += `Zwe`; + return `Zwe`; } - break; case "Ancient Chinese Revivalist": - r += `Chi Rev`; - break; + return `Chi Rev`; case "Ancient Egyptian Revivalist": - r += `Egy Rev`; - break; + return `Egy Rev`; case "Arabian Revivalist": - r += `Ara Rev`; - break; + return `Ara Rev`; case "Aztec Revivalist": - r += `Azt Rev`; - break; + return `Azt Rev`; case "Edo Revivalist": - r += `Edo Rev`; - break; + return `Edo Rev`; case "Roman Revivalist": - r += `Rom Rev`; - break; + return `Rom Rev`; case "": case "none": case "slave": case "Stateless": - r += `None`; - break; + return "None"; default: - r += `${slave.nationality.charAt(0) + slave.nationality.charAt(1) + slave.nationality.charAt(2)}`; - break; + return `${slave.nationality.charAt(0) + slave.nationality.charAt(1) + slave.nationality.charAt(2)}`; } - r += `</span> `; } /** * @param {App.Entity.SlaveState} slave + * @returns {string} */ function long_nationality(slave) { - r += `<span class="tan">`; switch (slave.nationality) { case "a Cook Islander": - r += `Cook Islander.`; - break; + return `Cook Islander.`; case "a Liechtensteiner": - r += `Liechtensteiner.`; - break; + return `Liechtensteiner.`; case "a New Zealander": - r += `New Zealander.`; - break; + return `New Zealander.`; case "a Solomon Islander": - r += `Solomon Islander.`; - break; + return `Solomon Islander.`; case "Zimbabwean": if (slave.race === "white") { - r += `Rhodesian.`; + return `Rhodesian.`; } else { - r += `${slave.nationality}.`; + return `${slave.nationality}.`; } - break; case "slave": case "none": case "": case "Stateless": - r += `Stateless.`; - break; + return `Stateless.`; default: - r += `${slave.nationality}.`; - break; + return `${slave.nationality}.`; } - r += `</span> `; } /** * @param {App.Entity.SlaveState} slave + * @returns {string} */ function short_skin(slave) { - r += `<span class="pink">`; switch (slave.skin) { case "pure white": - r += `P. Whi`; - break; + return `P. Whi`; case "extremely fair": - r += `E. Fai`; - break; + return `E. Fai`; case "very fair": - r += `V. Fai`; - break; + return `V. Fai`; case "extremely pale": - r += `E. Pal`; - break; + return `E. Pal`; case "very pale": - r += `V. Pal`; - break; + return `V. Pal`; case "light brown": - r += `L. Br`; - break; + return `L. Br`; case "dark brown": - r += `D. Br`; - break; + return `D. Br`; case "light olive": - r += `L. Oli`; - break; + return `L. Oli`; case "dark olive": - r += `D. Oli`; - break; + return `D. Oli`; case "light beige": - r += `L. Bei`; - break; + return `L. Bei`; case "dark beige": - r += `D. Bei`; - break; + return `D. Bei`; case "tan": - r += `Tan`; - break; + return `Tan`; case "bronze": - r += `Bron`; - break; + return `Bron`; case "ebony": - r += `Ebon`; - break; + return `Ebon`; case "pure black": - r += `P. Bla`; - break; + return `P. Bla`; case "dark": case "fair": case "pale": - r += `${slave.skin.charAt(0).toUpperCase() + slave.skin.slice(1)}`; - break; + return `${slave.skin.charAt(0).toUpperCase() + slave.skin.slice(1)}`; default: - r += `${slave.skin.charAt(0).toUpperCase() + slave.skin.charAt(1) + slave.skin.charAt(2)}`; - break; + return `${slave.skin.charAt(0).toUpperCase() + slave.skin.charAt(1) + slave.skin.charAt(2)}`; } - r += `</span> `; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_genitals(slave) { + function short_genitals(slave, c) { if (slave.dick > 0) { - r += `<span class="pink">`; + let dickDesc = ""; if (slave.balls === 0) { - r += `Geld`; + dickDesc += `Geld`; } if ((slave.dick > 8) && (slave.balls > 8)) { - r += `Junk+++`; + dickDesc += `Junk+++`; } else if ((slave.dick > 5) && (slave.balls > 5)) { - r += `Junk++`; + dickDesc += `Junk++`; } else if ((slave.dick > 4) && (slave.balls > 4)) { - r += `Junk+`; + dickDesc += `Junk+`; } else if ((slave.dick > 3) && (slave.balls > 3)) { - r += `Junk`; + dickDesc += `Junk`; } else if (slave.dick > 8) { - r += `Dick+++`; + dickDesc += `Dick+++`; } else if (slave.dick > 5) { - r += `Dick++`; + dickDesc += `Dick++`; } else if (slave.dick > 4) { - r += `Dick+`; + dickDesc += `Dick+`; } else if (slave.dick > 3) { - r += `Dick`; + dickDesc += `Dick`; } else if (slave.balls > 10) { - r += `Balls+++`; + dickDesc += `Balls+++`; } else if (slave.balls > 5) { - r += `Balls++`; + dickDesc += `Balls++`; } else if (slave.balls > 4) { - r += `Balls+`; + dickDesc += `Balls+`; } else if (slave.balls > 3) { - r += `Balls`; + dickDesc += `Balls`; + } + if (dickDesc.length) { + makeSpan(c, dickDesc, "pink"); } - r += `</span> `; } if (slave.vagina === 0) { - r += `<span class="lime">VV</span>`; + makeSpan(c, "VV", "lime"); } else if ((slave.pregKnown === 1) && canWalk(slave) && (slave.clothes === "no clothing" || slave.clothes === "body oil") && (slave.shoes === "none")) { - r += `<span class="pink">NBP</span>`; + makeSpan(c, "NBP", "pink"); } if (slave.anus === 0) { - r += ` <span class="lime">AV</span>`; + makeSpan(c, "AV", "lime"); } - r += `<span class="pink">`; + let holesDesc = ""; if ((slave.vagina > 3) && (slave.anus > 3)) { - r += ` V++A++`; + holesDesc += `V++A++`; } else if ((slave.vagina > 2) && (slave.anus > 2)) { - r += ` V+A+`; + holesDesc += `V+A+`; } else if (slave.vagina > 3) { - r += ` V++`; + holesDesc += `V++`; } else if (slave.vagina > 2) { - r += ` V+`; + holesDesc += `V+`; } else if (slave.anus > 3) { - r += ` A++`; + holesDesc += `A++`; } else if (slave.anus > 2) { - r += ` A+`; + holesDesc += `A+`; + } + if (holesDesc.length) { + makeSpan(c, holesDesc, "pink"); } - r += `</span> `; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_genitals(slave) { + function long_genitals(slave, c) { if (slave.dick > 0) { - r += `<span class="pink">`; + let dickDesc = ""; if (slave.balls === 0) { - r += `Gelded.`; + dickDesc += 'Gelded.'; } if ((slave.dick > 8) && (slave.balls > 8)) { - r += `Hyper dick & balls.`; + dickDesc += `Hyper dick & balls.`; } else if ((slave.dick > 5) && (slave.balls > 5)) { - r += `Monster dick & balls.`; + dickDesc += `Monster dick & balls.`; } else if ((slave.dick > 4) && (slave.balls > 4)) { - r += `Huge dick & balls.`; + dickDesc = `Huge dick & balls.`; } else if ((slave.dick > 3) && (slave.balls > 3)) { - r += `Big dick & balls.`; + dickDesc = `Big dick & balls.`; } else if (slave.dick > 8) { - r += `Hyper dong.`; + dickDesc = `Hyper dong.`; } else if (slave.dick > 5) { - r += `Monster dong.`; + dickDesc = `Monster dong.`; } else if (slave.dick > 4) { - r += `Huge dick.`; + dickDesc = `Huge dick.`; } else if (slave.dick > 3) { - r += `Big dick.`; + dickDesc = `Big dick.`; } else if (slave.balls > 8) { - r += `Hyper balls.`; + dickDesc = `Hyper balls.`; } else if (slave.balls > 5) { - r += `Monstrous balls.`; + dickDesc = `Monstrous balls.`; } else if (slave.balls > 4) { - r += `Huge balls.`; + dickDesc = `Huge balls.`; } else if (slave.balls > 3) { - r += `Big balls.`; + dickDesc = `Big balls.`; + } + if (dickDesc.length) { + makeSpan(c, dickDesc, "pink"); } - r += `</span> `; } if (slave.vagina === 0) { - r += `<span class="lime">Virgin.</span> `; + makeSpan(c, "Virgin.", "lime"); } else if ((slave.pregKnown === 1) && canWalk(slave) && (slave.clothes === "no clothing" || slave.clothes === "body oil") && (slave.shoes === "none")) { - r += `<span class="pink">Naked, barefoot, and pregnant.</span> `; + makeSpan(c, "Naked, barefoot, and pregnant.", "pink"); } if (slave.anus === 0) { - r += `<span class="lime">Anal virgin.</span> `; + makeSpan(c, "Anal virgin.", "lime"); } - r += `<span class="pink">`; + let holesDesc = ""; if ((slave.vagina > 3) && (slave.anus > 3)) { - r += `Blown out holes.`; + holesDesc += `Blown out holes.`; } else if ((slave.vagina > 2) && (slave.anus > 2)) { - r += `High mileage.`; + holesDesc += `High mileage.`; } else if (slave.vagina > 3) { - r += `Cavernous pussy.`; + holesDesc += `Cavernous pussy.`; } else if (slave.vagina > 2) { - r += `Loose pussy.`; + holesDesc += `Loose pussy.`; } else if (slave.anus > 3) { - r += `Permagaped anus.`; + holesDesc += `Permagaped anus.`; } else if (slave.anus > 2) { - r += `Gaping anus.`; + holesDesc += `Gaping anus.`; + } + if (holesDesc.length) { + makeSpan(c, holesDesc, "pink"); } - r += `</span> `; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_age(slave) { - r += `<span class="pink">`; + function short_age(slave, c) { + let r = makeSpan(c, "", "pink"); if (V.showAgeDetail === 1) { - r += slave.actualAge; + r.textContent += slave.actualAge.toString(); } else if (slave.actualAge >= 40) { - r += `40s`; + r.textContent += "40s"; } else if (slave.actualAge >= 35) { - r += `Lt30s`; + r.textContent += "Lt30s"; } else if (slave.actualAge >= 30) { - r += `Ea30s`; + r.textContent += "Ea30s"; } else if (slave.actualAge >= 25) { - r += `Lt20s`; + r.textContent += "Lt20s"; } else if (slave.actualAge >= 20) { - r += `Ea20s`; + r.textContent += "Ea20s"; } else if (slave.actualAge >= 18) { - r += slave.actualAge; + r.textContent += slave.actualAge.toString(); } if (slave.actualAge !== slave.physicalAge) { - r += ` w ${slave.physicalAge}y-bdy`; + r.textContent += ` w ${slave.physicalAge}y-bdy`; } if (slave.visualAge !== slave.physicalAge) { - r += ` Lks${slave.visualAge}`; + r.textContent += ` Lks${slave.visualAge}`; } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_face(slave) { + function short_face(slave, c) { if (slave.face < -95) { - r += `<span class="red">Face---${V.summaryStats? `[${slave.face}]` : ''}</span>`; + makeSpan(c, "Face---", "red", true, slave.face); } else if (slave.face < -40) { - r += `<span class="red">Face--${V.summaryStats? `[${slave.face}]` : ''}</span>`; + makeSpan(c, "Face--", "red", true, slave.face); } else if (slave.face < -10) { - r += `<span class="red">Face-${V.summaryStats? `[${slave.face}]` : ''}</span>`; + makeSpan(c, "Face-", "red", true, slave.face); } else if (slave.face <= 10) { - r += `Face${V.summaryStats? `[${slave.face}]` : ''}`; + makeSpan(c, "Face", null, true, slave.face); } else if (slave.face <= 40) { - r += `<span class="pink">Face+${V.summaryStats? `[${slave.face}]` : ''}</span>`; + makeSpan(c, "Face+", "pink", true, slave.face); } else if (slave.face <= 95) { - r += `<span class="pink">Face++${V.summaryStats? `[${slave.face}]` : ''}</span>`; + makeSpan(c, "Face++", "pink", true, slave.face); } else { - r += `<span class="pink">Face+++${V.summaryStats? `[${slave.face}]` : ''}</span>`; + makeSpan(c, "Face+++", "pink", true, slave.face); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_eyes(slave) { - if (slave.eyes <= -2) { - r += `<span class="red">Blind</span>`; + function short_eyes(slave, c) { + if (slave.eyes === -2) { + makeSpan(c, "Blind", "red"); } else if (((slave.eyes === -1) && (slave.eyewear !== "corrective glasses") && (slave.eyewear !== "corrective contacts")) || (slave.eyewear === "blurring glasses") || (slave.eyewear === "blurring contacts")) { - r += `<span class="yellow">Sight-</span>`; + makeSpan(c, "Sight-", "yellow"); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_ears(slave) { + function short_ears(slave, c) { if (slave.hears === -2) { - r += `<span class="red">Deaf</span>`; + makeSpan(c, "Deaf", "red"); } else if ((slave.hears === -1) && (slave.earwear !== "hearing aids")) { - r += `<span class="yellow">Hearing-</span>`; + makeSpan(c, "Hearing-", "yellow"); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_lips(slave) { + function short_lips(slave, c) { if (slave.lips > 95) { - r += `Facepussy`; + makeSpan(c, "Facepussy"); } else if (slave.lips > 70) { - r += `Lips+++${V.summaryStats? `[${slave.lips}]` : ''}`; + makeSpan(c, "Lips+++", null, true, slave.lips); } else if (slave.lips > 40) { - r += `Lips++${V.summaryStats? `[${slave.lips}]` : ''}`; + makeSpan(c, "Lips++", null, true, slave.lips); } else if (slave.lips > 20) { - r += `Lips+${V.summaryStats? `[${slave.lips}]` : ''}`; + makeSpan(c, "Lips+", null, true, slave.lips); } else if (slave.lips > 10) { - r += `Lips${V.summaryStats? `[${slave.lips}]` : ''}`; + makeSpan(c, "Lips", null, true, slave.lips); } else { - r += `<span class="red">Lips-${V.summaryStats? `[${slave.lips}]` : ''}</span>`; + makeSpan(c, "Lips-", "red", true, slave.lips); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_teeth(slave) { + function short_teeth(slave, c) { if (slave.teeth === "crooked") { - r += `<span class="yellow">Cr Teeth</span>`; + makeSpan(c, "Cr Teeth", "yellow"); } else if (slave.teeth === "gapped") { - r += `<span class="yellow">Gap</span>`; + makeSpan(c, "Gap", "yellow"); } else if (slave.teeth === "cosmetic braces") { - r += `Cos Braces`; + makeSpan(c, `Cos Braces`); } else if (slave.teeth === "straightening braces") { - r += `Braces`; + makeSpan(c, `Braces`); } else if (slave.teeth === "removable") { - r += `Rem Teeth`; + makeSpan(c, `Rem Teeth`); } else if (slave.teeth === "pointy") { - r += `Fangs`; + makeSpan(c, `Fangs`); } else if (slave.teeth === "baby") { - r += `Baby`; + makeSpan(c, `Baby`); } else if (slave.teeth === "mixed") { - r += `Mixed`; + makeSpan(c, `Mixed`); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_muscles(slave) { + function short_muscles(slave, c) { if (slave.muscles > 95) { - r += `Musc++${V.summaryStats? `[${slave.muscles}]`: ''}`; + makeSpan(c, "Musc++", undefined, true, slave.muscles); } else if (slave.muscles > 50) { - r += `Musc+${V.summaryStats? `[${slave.muscles}]`: ''}`; + makeSpan(c, "Musc+", undefined, true, slave.muscles); } else if (slave.muscles > 5) { - r += `Fit${V.summaryStats? `[${slave.muscles}]`: ''}`; + makeSpan(c, "Fit", undefined, true, slave.muscles); } else if (slave.muscles > -6) { - r += `Soft${V.summaryStats? `[${slave.muscles}]`: ''}`; + makeSpan(c, "Soft", undefined, true, slave.muscles); } else if (slave.muscles > -31) { if (V.arcologies[0].FSPhysicalIdealist === "unset") { - r += `<span class="red">Weak</span>${V.summaryStats? `[${slave.muscles}]`: ''}`; + makeSpan(c, "Weak", "red", true, slave.muscles); } else { - r += `Soft${V.summaryStats? `[${slave.muscles}]`: ''}`; + makeSpan(c, "Soft", undefined, true, slave.muscles); } } else if (slave.muscles > -96) { if (V.arcologies[0].FSPhysicalIdealist === "unset") { - r += `<span class="red">Weak+</span>${V.summaryStats? `[${slave.muscles}]`: ''}`; + makeSpan(c, "Weak+", "red", true, slave.muscles); } else { - r += `Soft+${V.summaryStats? `[${slave.muscles}]`: ''}`; + makeSpan(c, "Soft+", undefined, true, slave.muscles); } } else { - r += `<span class="red">Weak++</span>${V.summaryStats? `[${slave.muscles}]`: ''}`; + makeSpan(c, "Weak++", "red", true, slave.muscles); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_limbs(slave) { + function short_limbs(slave, c) { if (slave.amp !== 0) { if (slave.amp === -1) { - r += `P-Limbs`; + addText(c, "P-Limbs"); } else if (slave.amp === -2) { - r += `Sex P-Limbs`; + addText(c, "Sex P-Limbs"); } else if (slave.amp === -3) { - r += `Beauty P-Limbs`; + addText(c, "Beauty P-Limbs"); } else if (slave.amp === -4) { - r += `Combat P-Limbs`; + addText(c, "Combat P-Limbs"); } else if (slave.amp === -5) { - r += `Cyber P-Limbs`; + addText(c, "Cyber P-Limbs"); } else { - r += `Amp`; + addText(c, "Amp"); } } - r += " "; + addText(c, " "); if (!canWalk(slave)) { - r += ` Immob `; + addText(c, " Immob "); } if (slave.heels === 1) { - r += ` Heel `; + addText(c, " Heel "); } - r += `</span> `; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_voice(slave) { + function short_voice(slave, c) { if (slave.voice === 0) { - r += `<span class="red">Mute</span>`; + makeSpan(c, "Mute", "red"); } else { if (slave.accent === 3) { - r += `<span class="red">Acc--</span>`; + makeSpan(c, "Acc--", "red"); } else if (slave.accent === 2) { - r += `Acc-`; + makeSpan(c, "Acc-"); } else if (slave.accent === 4) { - r += `Acc--`; + makeSpan(c, "Acc--"); } else if (slave.accent === 1) { - r += `<span class="pink">Acc</span>`; + makeSpan(c, "Acc", "pink"); } } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_tits_ass(slave) { - r += `<span class="pink">`; + function short_tits_ass(slave, c) { + let styles = "pink"; if ((slave.boobs >= 12000) && (slave.butt > 9)) { - r += `T&A+++`; + makeSpan(c, "T&A+++", styles); } else if ((slave.boobs > 4000) && (slave.butt > 8)) { - r += `T&A++`; + makeSpan(c, "T&A++", styles); } else if ((slave.boobs > 2000) && (slave.butt > 6)) { - r += `T&A+`; + makeSpan(c, "T&A+", styles); } else if ((slave.boobs > 800) && (slave.butt > 4)) { - r += `T&A`; + makeSpan(c, "T&A", styles); } else if ((slave.boobs < 500) && (slave.butt < 3) && (slave.weight <= 10) && (slave.muscles <= 30)) { - r += `Girlish`; + makeSpan(c, "Girlish", styles); } else if (slave.boobs >= 12000) { - r += `Boobs+++`; + makeSpan(c, "Boobs+++", styles); } else if (slave.boobs > 4000) { - r += `Boobs++`; + makeSpan(c, "Boobs++", styles); } else if (slave.boobs > 2000) { - r += `Boobs+`; + makeSpan(c, "Boobs+", styles); } else if (slave.boobs > 800) { - r += `Boobs`; + makeSpan(c, "Boobs", styles); } else if (slave.butt > 9) { - r += `Ass+++`; + makeSpan(c, "Ass+++", styles); } else if (slave.butt > 8) { - r += `Ass++`; + makeSpan(c, "Ass++", styles); } else if (slave.butt > 6) { - r += `Ass+`; + makeSpan(c, "Ass+", styles); } else if (slave.butt > 4) { - r += `Ass`; + makeSpan(c, "Ass", styles); } - r += `</span> `; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_hips(slave) { - r += `<span class="red">`; + function short_hips(slave, c) { + let desc = ""; if (slave.hips < -1) { if (slave.butt > 2 && (V.arcologies[0].FSTransformationFetishist < 20 || V.arcologies[0].FSTransformationFetishist === "unset") && (V.arcologies[0].FSHedonisticDecadence < 20 || V.arcologies[0].FSHedonisticDecadence === "unset")) { - r += `Disp+`; + desc = `Disp+`; } } else if (slave.hips < 0) { if (slave.butt > 4 && (V.arcologies[0].FSTransformationFetishist < 20 || V.arcologies[0].FSTransformationFetishist === "unset") && (V.arcologies[0].FSHedonisticDecadence < 20 || V.arcologies[0].FSHedonisticDecadence === "unset")) { - r += `Disp+`; + desc = `Disp+`; } } else if (slave.hips > 2) { if (slave.butt <= 8) { - r += `Disp-`; + desc = `Disp-`; } } else if (slave.hips > 1) { if (slave.butt <= 3 && (V.arcologies[0].FSSlimnessEnthusiast === "unset" || (slave.boobs >= 500))) { - r += `Disp-`; + desc = `Disp-`; } } else if (slave.hips > 0) { if (slave.butt > 8) { if ((V.arcologies[0].FSTransformationFetishist < 20 || V.arcologies[0].FSTransformationFetishist === "unset") && (V.arcologies[0].FSHedonisticDecadence < 20 || V.arcologies[0].FSHedonisticDecadence === "unset")) { - r += `Disp+`; + desc = `Disp+`; } } else if (slave.butt <= 2 && (V.arcologies[0].FSSlimnessEnthusiast === "unset" || (slave.boobs >= 500))) { - r += `Disp-`; + desc = `Disp-`; } } else { if (slave.butt > 6) { if ((V.arcologies[0].FSTransformationFetishist < 20 || V.arcologies[0].FSTransformationFetishist === "unset") && (V.arcologies[0].FSHedonisticDecadence < 20 || V.arcologies[0].FSHedonisticDecadence === "unset")) { - r += `Disp+`; + desc = `Disp+`; } } else if (slave.butt <= 1 && (V.arcologies[0].FSSlimnessEnthusiast === "unset" || (slave.boobs >= 500))) { - r += `Disp-`; + desc = `Disp-`; } } - r += `</span> `; + if (desc) { + makeSpan(c, desc, "red"); + } } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_waist(slave) { + function short_waist(slave, c) { if (slave.waist > 95) { - r += `<span class="red">Wst---${V.summaryStats? `[${slave.waist}]` : ''}</span>`; + makeSpan(c, "Wst---", "red", false, slave.waist); } else if (slave.waist > 40) { - r += `<span class="red">Wst--${V.summaryStats? `[${slave.waist}]`: ''}</span>`; + makeSpan(c, "Wst--", "red", false, slave.waist); } else if (slave.waist > 10) { - r += `<span class="red">Wst-${V.summaryStats? `[${slave.waist}]` : ''}</span>`; + makeSpan(c, "Wst-", "red", false, slave.waist); } else if (slave.waist >= -10) { - r += `Wst${V.summaryStats? `[${slave.waist}]`: ''}`; + makeSpan(c, "Wst", undefined, false, slave.waist); } else if (slave.waist >= -40) { - r += `<span class="pink">Wst+${V.summaryStats? `[${slave.waist}]` : ''}</span>`; + makeSpan(c, "Wst+", "pink", false, slave.waist); } else if (slave.waist >= -95) { - r += `<span class="pink">Wst++${V.summaryStats? `[${slave.waist}]` : ''}</span>`; + makeSpan(c, "Wst++", "pink", false, slave.waist); } else { - r += `<span class="pink">Wst+++${V.summaryStats? `[${slave.waist}]`: ''}</span>`; + makeSpan(c, "Wst+++", "pink", false, slave.waist); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_implants(slave) { - r += `<span class="pink">`; + function short_implants(slave, c) { if ((slave.boobsImplant === 0) && (slave.buttImplant === 0) && (slave.waist >= -95) && (slave.lipsImplant === 0) && (slave.faceImplant <= 5) && (slave.bellyImplant === -1)) { - r += `Natr`; + makeSpan(c, "Natr", "pink"); } else { - r += `Impl`; + makeSpan(c, "Impl", "pink"); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_lactation(slave) { + function short_lactation(slave, c) { if (slave.lactation === 1) { - r += `Lact`; + makeSpan(c, "Lact", "pink"); } else if (slave.lactation === 2) { - r += `Lact++`; + makeSpan(c, "Lact", "pink"); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_mods(slave) { + function short_mods(slave, c) { V.modScore = SlaveStatsChecker.modScore(slave); if (slave.corsetPiercing === 0 && V.piercingScore < 3 && V.tatScore < 2) { return; } else if (V.modScore > 15 || (V.piercingScore > 8 && V.tatScore > 5)) { - r += `Mods++`; + makeSpan(c, "Mods++"); } else if (V.modScore > 7) { - r += `Mods+`; + makeSpan(c, "Mods+"); } else { - r += `Mods`; + makeSpan(c, "Mods"); } if (!jQuery.isEmptyObject(slave.brand)) { - r += `Br`; + makeSpan(c, "Br"); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_age(slave) { - r += `<span class="pink">`; + function long_age(slave, c) { + let r = makeSpan(c, "", "pink"); if (V.showAgeDetail === 1) { - r += `Age ` + `${slave.actualAge}` + `.`; + r.textContent += `Age ` + `${slave.actualAge}` + `.`; } else if (slave.actualAge >= 40) { - r += `Forties.`; + r.textContent += `Forties.`; } else if (slave.actualAge >= 35) { - r += `Late thirties.`; + r.textContent += `Late thirties.`; } else if (slave.actualAge >= 30) { - r += `Early thirties.`; + r.textContent += `Early thirties.`; } else if (slave.actualAge >= 25) { - r += `Late twenties.`; + r.textContent += `Late twenties.`; } else if (slave.actualAge >= 20) { - r += `Early twenties.`; + r.textContent += `Early twenties.`; } else if (slave.actualAge >= 19) { - r += `Nineteen.`; + r.textContent += `Nineteen.`; } else if (slave.actualAge >= 18) { - r += `Eighteen.`; + r.textContent += `Eighteen.`; } else { - r += `Underage.`; + r.textContent += `Underage.`; } - r += " "; + r.textContent += " "; /* ** No NCS, then do the standard, However because of the wrinkes of Incubators, as long as visual age is greater ** than or equal to physical age, we do the old physical body/Looks for fresh out of the can NCS slaves. */ if (((slave.geneMods.NCS === 0) || (slave.visualAge >= slave.physicalAge))) { if (slave.actualAge !== slave.physicalAge) { - r += `${slave.physicalAge}` + ` year old body. `; + r.textContent += `${slave.physicalAge}` + ` year old body. `; } if (slave.visualAge !== slave.physicalAge) { - r += `Looks ` + `${slave.visualAge}` + `. `; + r.textContent += `Looks ` + `${slave.visualAge}` + `. `; } } else { /* @@ -2465,1640 +2188,1580 @@ window.SlaveSummaryUncached = (function() { ** say: 'Age 1. 11 year old body.' -- this conflicts with the way NCS works though, because she hasn't ** visually aged, so our change here makes it say 'Age 1. Appears to have a 10 year old body.' */ - r += `Appears to have a ` + `${slave.visualAge}` + ` year old body. `; + r.textContent += `Appears to have a ` + `${slave.visualAge}` + ` year old body. `; } if (slave.geneMods.NCS === 1) { - r += `(<span class="orange">NCS</span>) `; + makeSpan(r, "NCS", "orange"); } } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_face(slave) { + function long_face(slave, c) { if (slave.face < -95) { - r += `<span class="red">Very ugly${V.summaryStats? `[${slave.face}]`: ''}</span>`; + return makeSpan(c, `Very ugly ${slave.faceShape} face`, "red", true, slave.face); } else if (slave.face < -40) { - r += `<span class="red">Ugly${V.summaryStats? `[${slave.face}]`: ''}</span>`; + return makeSpan(c, `Ugly ${slave.faceShape} face`, "red", true, slave.face); } else if (slave.face < -10) { - r += `<span class="red">Unattractive${V.summaryStats? `[${slave.face}]`: ''}</span>`; + return makeSpan(c, `Unattractive ${slave.faceShape} face`, "red", true, slave.face); } else if (slave.face <= 10) { - r += `Average${V.summaryStats? `[${slave.face}]`: ''}`; + return makeSpan(c, `Average ${slave.faceShape} face`, null, true, slave.face); } else if (slave.face <= 40) { - r += `<span class="pink">Attractive${V.summaryStats? `[${slave.face}]`: ''}</span>`; + return makeSpan(c, `Attractive ${slave.faceShape} face`, "pink", true, slave.face); } else if (slave.face <= 95) { - r += `<span class="pink">Beautiful${V.summaryStats? `[${slave.face}]`: ''}</span>`; + return makeSpan(c, `Beautiful ${slave.faceShape} face`, "pink", true, slave.face); } else { - r += `<span class="pink">Very beautiful${V.summaryStats? `[${slave.face}]`: ''}</span>`; + return makeSpan(c, `Very beautiful ${slave.faceShape} face`, "pink", true, slave.face); } - r += ` ${slave.faceShape} face. `; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_eyes(slave) { + function long_eyes(slave, c) { if (slave.eyes <= -2) { - r += `<span class="red">Blind.</span>`; + makeSpan(c, "Blind.", "red"); } else if (((slave.eyes === -1) && (slave.eyewear !== "corrective glasses") && (slave.eyewear !== "corrective contacts")) || (slave.eyewear === "blurring glasses") || (slave.eyewear === "blurring contacts")) { - r += `<span class="yellow">Nearsighted.</span>`; + makeSpan(c, "Nearsighted.", "yellow"); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_ears(slave) { + function long_ears(slave, c) { if (slave.hears <= -2) { - r += `<span class="red">Deaf.</span>`; + makeSpan(c, "Deaf.", "red"); } else if ((slave.hears === -1) && (slave.earwear !== "hearing aids")) { - r += `<span class="yellow">Hard of hearing.</span>`; + makeSpan(c, "Hard of hearing.", "yellow"); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_lips(slave) { + function long_lips(slave, c) { if (slave.lips > 95) { - r += `Facepussy${V.summaryStats? `[${slave.lips}]`: ''}.`; + makeSpan(c, "Facepussy", undefined, true, slave.lips); } else if (slave.lips > 70) { - r += `Huge lips${V.summaryStats? `[${slave.lips}]`: ''}.`; + makeSpan(c, "Huge lips", undefined, true, slave.lips); } else if (slave.lips > 40) { - r += `Big lips${V.summaryStats? `[${slave.lips}]`: ''}.`; + makeSpan(c, "Big lips", undefined, true, slave.lips); } else if (slave.lips > 20) { - r += `Pretty lips${V.summaryStats? `[${slave.lips}]`: ''}.`; + makeSpan(c, "Pretty lips", undefined, true, slave.lips); } else if (slave.lips > 10) { - r += `Normal lips${V.summaryStats? `[${slave.lips}]`: ''}.`; + makeSpan(c, "Normal lips", undefined, true, slave.lips); } else { - r += `<span class="red">Thin lips${V.summaryStats? `[${slave.lips}]`: ''}.</span>`; + makeSpan(c, "Thin lips", "red", true, slave.lips); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_teeth(slave) { + function long_teeth(slave, c) { if (slave.teeth === "crooked") { - r += `<span class="yellow">Crooked teeth.</span>`; + makeSpan(c, "Crooked teeth.", "yellow"); } else if (slave.teeth === "gapped") { - r += `<span class="yellow">Tooth gap.</span>`; + makeSpan(c, "Tooth gap.", "yellow"); } else if (slave.teeth === "cosmetic braces") { - r += `Cosmetic braces.`; + makeSpan(c, "Cosmetic braces."); } else if (slave.teeth === "straightening braces") { - r += `Braces.`; + makeSpan(c, "Braces."); } else if (slave.teeth === "removable") { - r += `Removable teeth.`; + makeSpan(c, "Removable teeth."); } else if (slave.teeth === "pointy") { - r += `Sharp fangs.`; + makeSpan(c, "Sharp fangs."); } else if (slave.teeth === "baby") { - r += `Baby teeth.`; + makeSpan(c, "Baby teeth."); } else if (slave.teeth === "mixed") { - r += `Mixed teeth.`; + makeSpan(c, "Mixed teeth."); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_muscles(slave) { + function long_muscles(slave, c) { if (slave.muscles > 95) { - r += `Hugely muscular${V.summaryStats? `[${slave.muscles}]` : ''}.`; + makeSpan(c, "Hugely muscular", undefined, true, slave.muscles); } else if (slave.muscles > 50) { - r += `Muscular${V.summaryStats? `[${slave.muscles}]`: ''}.`; + makeSpan(c, "Muscular", undefined, true, slave.muscles); } else if (slave.muscles > 5) { - r += `Fit${V.summaryStats? `[${slave.muscles}]`: ''}.`; + makeSpan(c, "Fit", undefined, true, slave.muscles); } else if (slave.muscles > -6) { - r += `Soft${V.summaryStats? `[${slave.muscles}]`: ''}.`; + makeSpan(c, "Soft", undefined, true, slave.muscles); } else if (slave.muscles > -31) { if (V.arcologies[0].FSPhysicalIdealist === "unset") { - r += `<span class="red">Weak${V.summaryStats? `[${slave.muscles}]`: ''}.</span>`; + makeSpan(c, "Weak", "red", true, slave.muscles); } else { - r += `Weak${V.summaryStats? `[${slave.muscles}]`: ''}.`; + makeSpan(c, "Weak", undefined, true, slave.muscles); } } else if (slave.muscles > -96) { if (V.arcologies[0].FSPhysicalIdealist === "unset") { - r += `<span class="red">Very weak${V.summaryStats? `[${slave.muscles}]`: ''}.</span>`; + makeSpan(c, "Very weak", "red", true, slave.muscles); } else { - r += `Very weak${V.summaryStats? `[${slave.muscles}]`: ''}.`; + makeSpan(c, "Very weak", undefined, true, slave.muscles); } } else { - r += `<span class="red">Frail${V.summaryStats? `[${slave.muscles}]`: ''}.</span>`; + makeSpan(c, "Frail", "red", true, slave.muscles); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_limbs(slave) { + function long_limbs(slave, c) { if (slave.amp !== 0) { if (slave.amp === -1) { - r += `Prosthetic limbs.`; + makeSpan(c, `Prosthetic limbs.`); } else if (slave.amp === -2) { - r += `Sexy prosthetic limbs.`; + makeSpan(c, `Sexy prosthetic limbs.`); } else if (slave.amp === -3) { - r += `Beautiful prosthetic limbs.`; + makeSpan(c, `Beautiful prosthetic limbs.`); } else if (slave.amp === -4) { - r += `Deadly prosthetic limbs.`; + makeSpan(c, `Deadly prosthetic limbs.`); } else if (slave.amp === -5) { - r += `Cyber prosthetic limbs.`; + makeSpan(c, `Cyber prosthetic limbs.`); } else { - r += `Amputee.`; + makeSpan(c, `Amputee.`); } } - r += " "; if (!canWalk(slave)) { - r += `Immobile. `; + makeSpan(c, "Immobile."); } if (slave.heels === 1) { - r += `Heeled. `; + makeSpan(c, "Heeled."); } - r += `</span> `; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_voice(slave) { + function long_voice(slave, c) { if (slave.voice === 0) { - r += `<span class="red">Mute.</span>`; + makeSpan(c, "Mute.", "red"); } else { if (slave.accent === 3) { - r += `<span class="red">Bad accent.</span>`; + makeSpan(c, "Bad accent.", "red"); } else if (slave.accent === 4) { - r += `<span class="red">No language skills.</span>`; + makeSpan(c, "No language skills.", "red"); } else if (slave.accent === 2) { - r += `Accent.`; + makeSpan(c, "Accent."); } else if (slave.accent === 1) { - r += `<span class="pink">Cute accent.</span>`; + makeSpan(c, "Cute accent.", "pink"); } } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_tits_ass(slave) { - r += `<span class="pink">`; + function long_tits_ass(slave, c) { + const styles = "pink"; if ((slave.boobs >= 12000) && (slave.butt > 9)) { - r += `Hyper T&A.`; + makeSpan(c, "Hyper T&A.", styles); } else if ((slave.boobs > 4000) && (slave.butt > 8)) { - r += `Enormous T&A.`; + makeSpan(c, "Enormous T&A.", styles); } else if ((slave.boobs > 2000) && (slave.butt > 6)) { - r += `Huge T&A.`; + makeSpan(c, "Huge T&A.", styles); } else if ((slave.boobs > 800) && (slave.butt > 4)) { - r += `Big T&A.`; + makeSpan(c, "Big T&A.", styles); } else if ((slave.boobs < 500) && (slave.butt < 3) && (slave.weight <= 10) && (slave.muscles <= 30)) { - r += `Girlish figure.`; + makeSpan(c, "Girlish figure.", styles); } else if (slave.boobs >= 12000) { - r += `Immobilizing tits.`; + makeSpan(c, "Immobilizing tits.", styles); } else if (slave.boobs > 4000) { - r += `Monstrous tits.`; + makeSpan(c, "Monstrous tits.", styles); } else if (slave.boobs > 2000) { - r += `Huge tits.`; + makeSpan(c, "Huge tits.", styles); } else if (slave.boobs > 800) { - r += `Big tits.`; + makeSpan(c, "Big tits.", styles); } else if (slave.butt > 9) { - r += `Hyper ass.`; + makeSpan(c, "Hyper ass.", styles); } else if (slave.butt > 8) { - r += `Titanic ass.`; + makeSpan(c, "Titanic ass.", styles); } else if (slave.butt > 6) { - r += `Huge ass.`; + makeSpan(c, "Huge ass.", styles); } else if (slave.butt > 4) { - r += `Big ass.`; + makeSpan(c, "Big ass.", styles); } - r += `</span> `; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_hips(slave) { - r += `<span class="red">`; + function long_hips(slave, c) { + const styles = "red"; if (slave.hips < -1) { if (slave.butt > 2 && (V.arcologies[0].FSTransformationFetishist < 20 || V.arcologies[0].FSTransformationFetishist === "unset") && (V.arcologies[0].FSHedonisticDecadence < 20 || V.arcologies[0].FSHedonisticDecadence === "unset") && (V.arcologies[0].FSAssetExpansionist < 20 || V.arcologies[0].FSAssetExpansionist === "unset")) { - r += `Disproportionately big butt.`; + makeSpan(c, "Disproportionately big butt.", styles); } } else if (slave.hips < 0) { if (slave.butt > 4 && (V.arcologies[0].FSTransformationFetishist < 20 || V.arcologies[0].FSTransformationFetishist === "unset") && (V.arcologies[0].FSHedonisticDecadence < 20 || V.arcologies[0].FSHedonisticDecadence === "unset") && (V.arcologies[0].FSAssetExpansionist < 20 || V.arcologies[0].FSAssetExpansionist === "unset")) { - r += `Disproportionately big butt.`; + makeSpan(c, "Disproportionately big butt.", styles); } } else if (slave.hips > 2) { if (slave.butt <= 8) { - r += `Disproportionately small butt.`; + makeSpan(c, "Disproportionately small butt.", styles); } } else if (slave.hips > 1) { if (slave.butt <= 3 && ((V.arcologies[0].FSSlimnessEnthusiast === "unset") || (slave.boobs >= 500))) { - r += `Disproportionately small butt.`; + makeSpan(c, "Disproportionately small butt.", styles); } } else if (slave.hips > 0) { if (slave.butt > 8) { if ((V.arcologies[0].FSTransformationFetishist < 20 || V.arcologies[0].FSTransformationFetishist === "unset") && (V.arcologies[0].FSHedonisticDecadence < 20 || V.arcologies[0].FSHedonisticDecadence === "unset") && (V.arcologies[0].FSAssetExpansionist < 20 || V.arcologies[0].FSAssetExpansionist === "unset")) { - r += `Disproportionately big butt.`; + makeSpan(c, "Disproportionately big butt.", styles); } } else if (slave.butt <= 2 && ((V.arcologies[0].FSSlimnessEnthusiast === "unset") || (slave.boobs >= 500))) { - r += `Disproportionately small butt.`; + makeSpan(c, "Disproportionately small butt.", styles); } } else { if (slave.butt > 6) { if ((V.arcologies[0].FSTransformationFetishist < 20 || V.arcologies[0].FSTransformationFetishist === "unset") && (V.arcologies[0].FSHedonisticDecadence < 20 || V.arcologies[0].FSHedonisticDecadence === "unset") && (V.arcologies[0].FSAssetExpansionist < 20 || V.arcologies[0].FSAssetExpansionist === "unset")) { - r += `Disproportionately big butt.`; + makeSpan(c, "Disproportionately big butt.", styles); } } else if (slave.butt <= 1 && ((V.arcologies[0].FSSlimnessEnthusiast === "unset") || (slave.boobs >= 500))) { - r += `Disproportionately small butt.`; + makeSpan(c, "Disproportionately small butt.", styles); } } - r += `</span> `; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_waist(slave) { + function long_waist(slave, c) { if (slave.waist > 95) { - r += `<span class="red">Masculine waist${V.summaryStats? `[${slave.waist}]`: ''}.</span>`; + makeSpan(c, "Masculine waist", "red", true, slave.waist); } else if (slave.waist > 40) { - r += `<span class="red">Ugly waist${V.summaryStats? `[${slave.waist}]`: ''}.</span>`; + makeSpan(c, "Ugly waist", "red", true, slave.waist); } else if (slave.waist > 10) { - r += `<span class="red">Unattractive waist${V.summaryStats? `[${slave.waist}]`: ''}.</span>`; + makeSpan(c, "Unattractive waist", "red", true, slave.waist); } else if (slave.waist >= -10) { - r += `Average waist${V.summaryStats? `[${slave.waist}]`: ''}.`; + makeSpan(c, "Average waist", null, true, slave.waist); } else if (slave.waist >= -40) { - r += `<span class="pink">Feminine waist${V.summaryStats? `[${slave.waist}]`: ''}.</span>`; + makeSpan(c, "Feminine waist", "pink", true, slave.waist); } else if (slave.waist >= -95) { - r += `<span class="pink">Hourglass waist${V.summaryStats? `[${slave.waist}]`: ''}.</span>`; + makeSpan(c, "Hourglass waist", "pink", true, slave.waist); } else { - r += `<span class="pink">Absurdly narrow waist${V.summaryStats? `[${slave.waist}]`: ''}.</span>`; + makeSpan(c, "Absurdly narrow waist", "pink", true, slave.waist); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_implants(slave) { - r += `<span class="pink">`; + function long_implants(slave, c) { + const styles = "pink"; if ((slave.boobsImplant !== 0) || (slave.buttImplant !== 0) || (slave.lipsImplant !== 0) || (slave.bellyImplant !== -1)) { - r += `Implants.`; + makeSpan(c, "Implants.", styles); } else if ((slave.faceImplant >= 30) || (slave.waist < -95)) { - r += `Surgery enhanced.`; + makeSpan(c, "Surgery enhanced.", styles); } else { - r += `All natural.`; + makeSpan(c, "All natural.", styles); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_lactation(slave) { + function long_lactation(slave, c) { if (slave.lactation === 1) { - r += `Lactating naturally.`; + makeSpan(c, "Lactating naturally.", "pink"); } else if (slave.lactation === 2) { - r += `Heavy lactation.`; + makeSpan(c, "Heavy lactation.", "pink"); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_mods(slave) { + function long_mods(slave, c) { V.modScore = SlaveStatsChecker.modScore(slave); if (slave.corsetPiercing === 0 && V.piercingScore < 3 && V.tatScore < 2) { return; } else if (V.modScore > 15 || (V.piercingScore > 8 && V.tatScore > 5)) { - r += `Extensive body mods.`; + makeSpan(c, "Extensive body mods."); } else if (V.modScore > 7) { - r += `Noticeable body mods.`; + makeSpan(c, "Noticeable body mods."); } else { - r += `Light body mods.`; + makeSpan(c, "Light body mods."); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_intelligence(slave) { + function short_intelligence(slave, c) { const intelligence = slave.intelligence + slave.intelligenceImplant; if (slave.fetish === "mindbroken") { return; - } else if (slave.intelligenceImplant >= 30) { - if (intelligence >= 130) { - r += `<span class="deepskyblue">I++++(e+)${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}</span>`; - } else if (intelligence > 95) { - r += `<span class="deepskyblue">I+++(e+)${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}</span>`; - } else if (intelligence > 50) { - r += `<span class="deepskyblue">I++(e+)${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}</span>`; - } else if (intelligence > 15) { - r += `<span class="deepskyblue">I+(e+)${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}</span>`; - } else if (intelligence >= -15) { - r += `I(e+)${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}`; - } else if (intelligence >= -50) { - r += `<span class="orangered">I-(e+)${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}</span>`; - } else if (intelligence >= -95) { - r += `<span class="orangered">I--(e+)${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}</span>`; - } else { - r += `<span class="orangered">I---(e+)${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}</span>`; - } + } + let education = ""; + let naturalIntelligence = ""; + let styles = undefined; + if (slave.intelligenceImplant >= 30) { + education = "(e+)"; } else if (slave.intelligenceImplant >= 15) { - if (intelligence > 95) { - r += `<span class="deepskyblue">I+++(e)${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}</span>`; - } else if (intelligence > 50) { - r += `<span class="deepskyblue">I++(e)${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}</span>`; - } else if (intelligence > 15) { - r += `<span class="deepskyblue">I+(e)${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}</span>`; - } else if (intelligence >= -15) { - r += `I(e)${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}`; - } else if (intelligence >= -50) { - r += `<span class="orangered">I-(e)${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}</span>`; - } else if (intelligence >= -95) { - r += `<span class="orangered">I--(e)${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}</span>`; - } else { - r += `<span class="orangered">I---(e)${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}</span>`; - } + education = "(e)"; + } + if (intelligence >= 130) { + naturalIntelligence = "I++++"; + styles = "deepskyblue"; + } else if (intelligence > 95) { + naturalIntelligence = "I+++"; + styles = "deepskyblue"; + } else if (intelligence > 50) { + naturalIntelligence = "I++"; + styles = "deepskyblue"; + } else if (intelligence > 15) { + naturalIntelligence = "I+"; + styles = "deepskyblue"; + } else if (intelligence >= -15) { + naturalIntelligence = "I"; + } else if (intelligence >= -50) { + naturalIntelligence = "I-"; + styles = "orangered"; + } else if (intelligence >= -95) { + naturalIntelligence = "I--"; + styles = "orangered"; } else { - if (intelligence > 95) { - r += `<span class="deepskyblue">I+++${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}</span>`; - } else if (intelligence > 50) { - r += `<span class="deepskyblue">I++${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}</span>`; - } else if (intelligence > 15) { - r += `<span class="deepskyblue">I+${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}</span>`; - } else if (intelligence >= -15) { - r += `I${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}`; - } else if (intelligence >= -50) { - r += `<span class="orangered">I-${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}</span>`; - } else if (intelligence >= -95) { - r += `<span class="orangered">I--${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}</span>`; - } else { - r += `<span class="orangered">I---${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}</span>`; - } + naturalIntelligence = "I---"; + styles = "orangered"; } - r += " "; + makeSpan(c, `${naturalIntelligence}${education}`, styles, true, intelligence); } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_sex_skills(slave) { + function short_skills(slave, c) { let _SSkills = slave.skill.anal + slave.skill.oral; - r += `<span class="aquamarine">`; + let r = makeSpan(c, "", "aquamarine"); if (((_SSkills + slave.skill.whoring + slave.skill.entertainment) >= 400) && ((slave.vagina < 0) || (slave.skill.vaginal >= 100))) { - r += `MSS`; + r.textContent += `MSS`; } else { _SSkills += slave.skill.vaginal; _SSkills = Math.trunc(_SSkills); if (_SSkills > 180) { - r += `S++`; + r.textContent += `S++`; } else if ((_SSkills > 120) && (slave.vagina < 0)) { - r += `Sh++`; + r.textContent += `Sh++`; } else if (_SSkills > 90) { - r += `S+`; + r.textContent += `S+`; } else if (_SSkills > 30) { - r += `S`; + r.textContent += `S`; } else { - r += `S-`; + r.textContent += `S-`; } if (V.summaryStats) { - r += `[${_SSkills}] `; + r.textContent += `[${_SSkills}]`; } - r += " "; + r.textContent += " "; if (slave.skill.whoring >= 100) { - r += `W+++`; + r.textContent += `W+++`; } else if (slave.skill.whoring > 60) { - r += `W++`; + r.textContent += `W++`; } else if (slave.skill.whoring > 30) { - r += `W+`; + r.textContent += `W+`; } else if (slave.skill.whoring > 10) { - r += `W`; + r.textContent += `W`; } if (slave.skill.whoring > 10) { if (V.summaryStats) { - r += `[${slave.skill.whoring}] `; + r.textContent += `[${slave.skill.whoring}]`; } } - r += " "; + r.textContent += " "; if (slave.skill.entertainment >= 100) { - r += `E+++`; + r.textContent += `E+++`; } else if (slave.skill.entertainment > 60) { - r += `E++`; + r.textContent += `E++`; } else if (slave.skill.entertainment > 30) { - r += `E+`; + r.textContent += `E+`; } else if (slave.skill.entertainment > 10) { - r += `E`; + r.textContent += `E`; } if (slave.skill.entertainment > 10) { if (V.summaryStats) { - r += `[${slave.skill.entertainment}] `; + r.textContent += `[${slave.skill.entertainment}]`; } } } - r += " "; + if (slave.skill.combat > 0) { + r.textContent += " C"; + } } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_prestige(slave) { + function short_prestige(slave, c) { if (slave.prestige > 0) { - r += `<span class="green">`; + const styles = "green"; if (slave.prestige > 2) { - r += `Prest++`; + makeSpan(c, "Prest++", styles); } else if (slave.prestige === 2) { - r += `Prest+`; + makeSpan(c, "Prest+", styles); } else if (slave.prestige === 1) { - r += `Prest`; + makeSpan(c, "Prest", styles); } - r += `</span> `; } } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_porn_prestige(slave) { + function short_porn_prestige(slave, c) { if (slave.pornPrestige > 0) { - r += `<span class="green">`; + const styles = "green"; if (slave.pornPrestige > 2) { - r += `PPrest++`; + makeSpan(c, "PPrest++", styles); } else if (slave.pornPrestige === 2) { - r += `PPrest+`; + makeSpan(c, "PPrest+", styles); } else if (slave.pornPrestige === 1) { - r += `PPrest`; + makeSpan(c, "PPrest", styles); } - r += `</span> `; } } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_intelligence(slave) { + function long_intelligence(slave, c) { const intelligence = slave.intelligence + slave.intelligenceImplant; if (slave.fetish === "mindbroken") { return; - } else if (slave.intelligenceImplant >= 30) { - if (intelligence >= 130) { - r += `<span class="deepskyblue">Genius${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}.</span>`; - } else if (intelligence > 95) { - r += `<span class="deepskyblue">Brilliant, well educated${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}.</span>`; - } else if (intelligence > 50) { - r += `<span class="deepskyblue">Very smart, well educated${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}.</span>`; - } else if (intelligence > 15) { - r += `<span class="deepskyblue">Smart, well educated${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}.</span>`; - } else if (intelligence >= -15) { - r += `Average intelligence, well educated${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}.`; - } else if (intelligence >= -50) { - r += `<span class="orangered">Slow, well educated${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}.</span>`; - } else if (intelligence >= -95) { - r += `<span class="orangered">Very slow, well educated${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}.</span>`; - } else { - r += `<span class="orangered">Moronic, well educated${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}.</span>`; - } + } + let education = ""; + let naturalIntelligence = ""; + let styles = undefined; + if (slave.intelligenceImplant >= 30) { + education = ", well educated"; } else if (slave.intelligenceImplant >= 15) { - if (intelligence > 95) { - r += `<span class="deepskyblue">Brilliant, educated${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}.</span>`; - } else if (intelligence > 50) { - r += `<span class="deepskyblue">Very smart, educated${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}.</span>`; - } else if (intelligence > 15) { - r += `<span class="deepskyblue">Smart, educated${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}.</span>`; - } else if (intelligence >= -15) { - r += `Average intelligence, educated${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}.`; - } else if (intelligence >= -50) { - r += `<span class="orangered">Slow, educated${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}.</span>`; - } else if (intelligence >= -95) { - r += `<span class="orangered">Very slow, educated${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}.</span>`; - } else { - r += `<span class="orangered">Moronic, educated${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}.</span>`; - } + education = ", educated"; + } + if (intelligence >= 130) { + naturalIntelligence = "Genius"; + styles = "deepskyblue"; + } else if (intelligence > 95) { + naturalIntelligence = "Brilliant"; + styles = "deepskyblue"; + } else if (intelligence > 50) { + naturalIntelligence = "Very smart"; + styles = "deepskyblue"; + } else if (intelligence > 15) { + naturalIntelligence = "Smart"; + styles = "deepskyblue"; + } else if (intelligence >= -15) { + naturalIntelligence = "Average intelligence"; + } else if (intelligence >= -50) { + naturalIntelligence = "Slow"; + styles = "orangered"; + } else if (intelligence >= -95) { + naturalIntelligence = "Very slow"; + styles = "orangered"; } else { - if (intelligence > 95) { - r += `<span class="deepskyblue">Brilliant${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}.</span>`; - } else if (intelligence > 50) { - r += `<span class="deepskyblue">Very smart${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}.</span>`; - } else if (intelligence > 15) { - r += `<span class="deepskyblue">Smart${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}.</span>`; - } else if (intelligence >= -15) { - r += `Average intelligence${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}.`; - } else if (intelligence >= -50) { - r += `<span class="orangered">Slow${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}.</span>`; - } else if (intelligence >= -95) { - r += `<span class="orangered">Very slow${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}.</span>`; - } else { - r += `<span class="orangered">Moronic${V.summaryStats ? `[${slave.intelligence+slave.intelligenceImplant}]` : ''}.</span>`; - } + naturalIntelligence = "Moronic"; + styles = "orangered"; } - r += " "; + makeSpan(c, `${naturalIntelligence}${education}`, styles, true, intelligence); } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_sex_skills(slave) { + function long_skills(slave, c) { let _SSkills = (slave.skill.anal + slave.skill.oral); - r += `<span class="aquamarine">`; if (((_SSkills + slave.skill.whoring + slave.skill.entertainment) >= 400) && ((slave.vagina < 0) || (slave.skill.vaginal >= 100))) { - r += `Masterful Sex Slave. `; + makeSpan(c, "Masterful Sex Slave.", "aquamarine"); } else { + let desc; _SSkills += slave.skill.vaginal; if (_SSkills > 180) { - r += `Sex master${V.summaryStats? `[${Math.trunc(_SSkills)}]`: ''}.`; + desc = "Sex master"; } else if ((_SSkills > 120) && (slave.vagina < 0)) { - r += `Masterful shemale${V.summaryStats? `[${Math.trunc(_SSkills)}]`: ''}.`; + desc = "Masterful shemale"; } else if (_SSkills > 90) { - r += `Sexual expert${V.summaryStats? `[${Math.trunc(_SSkills)}]`: ''}.`; + desc = "Sexual expert"; } else if (_SSkills > 30) { - r += `Sexually skilled${V.summaryStats? `[${Math.trunc(_SSkills)}]` : ''}.`; + desc = "Sexually skilled"; } else { - r += `Sexually unskilled${V.summaryStats? `[${Math.trunc(_SSkills)}]` : ''}.`; + desc = "Sexually unskilled"; + } + if (desc) { + makeSpan(c, desc, "aquamarine", true, Math.trunc(_SSkills)); + desc = ""; } - r += " "; if (slave.skill.whoring >= 100) { - r += `Masterful whore${V.summaryStats? `[${slave.skill.whoring}]`: ''}.`; + desc = "Masterful whore"; } else if (slave.skill.whoring >= 60) { - r += `Expert whore${V.summaryStats? `[${slave.skill.whoring}]`: ''}.`; + desc = "Expert whore"; } else if (slave.skill.whoring >= 30) { - r += `Skilled whore${V.summaryStats? `[${slave.skill.whoring}]`: ''}.`; + desc = "Skilled whore"; } else if (slave.skill.whoring >= 10) { - r += `Basic whore${V.summaryStats? `[${slave.skill.whoring}]`: ''}.`; + desc = "Basic whore"; + } + if (desc) { + makeSpan(c, desc, "aquamarine", true, slave.skill.whoring); + desc = ""; } - r += " "; if (slave.skill.entertainment >= 100) { - r += `Masterful entertainer${V.summaryStats? `[${slave.skill.entertainment}]`: ''}.`; + desc = "Masterful entertainer"; } else if (slave.skill.entertainment >= 60) { - r += `Expert entertainer${V.summaryStats? `[${slave.skill.entertainment}]`: ''}.`; + desc = "Expert entertainer"; } else if (slave.skill.entertainment >= 30) { - r += `Skilled entertainer${V.summaryStats? `[${slave.skill.entertainment}]`: ''}.`; + desc = "Skilled entertainer"; } else if (slave.skill.entertainment >= 10) { - r += `Basic entertainer${V.summaryStats? `[${slave.skill.entertainment}]`: ''}.`; + desc = "Basic entertainer"; } - r += " "; + if (desc) { + makeSpan(c, desc, "aquamarine", true, slave.skill.entertainment); + desc = ""; + } + } + if (slave.skill.combat > 0) { + makeSpan(c, "Trained fighter.", "aquamarine"); } } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_prestige(slave) { + function long_prestige(slave, c) { if (slave.prestige > 0) { - r += `<span class="green">`; + const styles = "green"; if (slave.prestige > 2) { - r += `Extremely prestigious.`; + makeSpan(c, "Extremely prestigious.", styles); } else if (slave.prestige === 2) { - r += `Very prestigious.`; + makeSpan(c, "Very prestigious.", styles); } else if (slave.prestige === 1) { - r += `Prestigious.`; + makeSpan(c, "Prestigious.", styles); } - r += `</span> `; } } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_porn_prestige(slave) { + function long_porn_prestige(slave, c) { if (slave.pornPrestige > 0) { - r += `<span class="green">`; + const styles = "green"; if (slave.pornPrestige > 2) { - r += `Porn star.`; + makeSpan(c, "Porn star.", styles); } else if (slave.pornPrestige === 2) { - r += `Porn slut.`; + makeSpan(c, "Porn slut.", styles); } else if (slave.pornPrestige === 1) { - r += `Porn amateur.`; + makeSpan(c, "Porn amateur.", styles); } - r += `</span> `; } } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_fetish(slave) { - r += `<span class="lightcoral">`; + function short_fetish(slave, c) { + let descStr = ""; switch (slave.fetish) { case "submissive": if (slave.fetishStrength > 95) { - r += `Sub++`; + descStr = `Sub++`; } else if (slave.fetishStrength > 60) { - r += `Sub+`; + descStr = `Sub+`; } else { - r += `Sub`; + descStr = `Sub`; } break; case "cumslut": if (slave.fetishStrength > 95) { - r += `Oral++`; + descStr = `Oral++`; } else if (slave.fetishStrength > 60) { - r += `Oral+`; + descStr = `Oral+`; } else { - r += `Oral`; + descStr = `Oral`; } break; case "humiliation": if (slave.fetishStrength > 95) { - r += `Humil++`; + descStr = `Humil++`; } else if (slave.fetishStrength > 60) { - r += `Humil+`; + descStr = `Humil+`; } else { - r += `Humil`; + descStr = `Humil`; } break; case "buttslut": if (slave.fetishStrength > 95) { - r += `Anal++`; + descStr = `Anal++`; } else if (slave.fetishStrength > 60) { - r += `Anal+`; + descStr = `Anal+`; } else { - r += `Anal`; + descStr = `Anal`; } break; case "boobs": if (slave.fetishStrength > 95) { - r += `Boobs++`; + descStr = `Boobs++`; } else if (slave.fetishStrength > 60) { - r += `Boobs+`; + descStr = `Boobs+`; } else { - r += `Boobs`; + descStr = `Boobs`; } break; case "sadist": if (slave.fetishStrength > 95) { - r += `Sadist++`; + descStr = `Sadist++`; } else if (slave.fetishStrength > 60) { - r += `Sadist+`; + descStr = `Sadist+`; } else { - r += `Sadist`; + descStr = `Sadist`; } break; case "masochist": if (slave.fetishStrength > 95) { - r += `Pain++`; + descStr = `Pain++`; } else if (slave.fetishStrength > 60) { - r += `Pain+`; + descStr = `Pain+`; } else { - r += `Pain`; + descStr = `Pain`; } break; case "dom": if (slave.fetishStrength > 95) { - r += `Dom++`; + descStr = `Dom++`; } else if (slave.fetishStrength > 60) { - r += `Dom+`; + descStr = `Dom+`; } else { - r += `Dom`; + descStr = `Dom`; } break; case "pregnancy": if (slave.fetishStrength > 95) { - r += `Preg++`; + descStr = `Preg++`; } else if (slave.fetishStrength > 60) { - r += `Preg+`; + descStr = `Preg+`; } else { - r += `Preg`; + descStr = `Preg`; } break; default: - r += `Vanilla`; + descStr = `Vanilla`; break; } if (V.summaryStats) { - r += `[${slave.fetishStrength}]`; + descStr += `[${slave.fetishStrength}]`; } - r += `</span> `; + makeSpan(c, descStr, "lightcoral"); } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_attraction(slave) { + function short_attraction(slave, c) { if (slave.attrXY <= 5) { - r += `<span class="red">XY---${V.summaryStats? `[${slave.attrXY}]`: ''}</span>`; + makeSpan(c, "XY---", "red", false, slave.attrXY); } else if (slave.attrXY <= 15) { - r += `<span class="red">XY--${V.summaryStats? `[${slave.attrXY}]`: ''}</span>`; + makeSpan(c, "XY--", "red", false, slave.attrXY); } else if (slave.attrXY <= 35) { - r += `<span class="red">XY-${V.summaryStats? `[${slave.attrXY}]`: ''}</span>`; + makeSpan(c, "XY---", "red", false, slave.attrXY); } else if (slave.attrXY <= 65) { - r += `XY${V.summaryStats? `[${slave.attrXY}]`: ''}`; + makeSpan(c, "XY", undefined, false, slave.attrXY); } else if (slave.attrXY <= 85) { - r += `<span class="green">XY+${V.summaryStats? `[${slave.attrXY}]`: ''}</span>`; + makeSpan(c, "XY+", "green", false, slave.attrXY); } else if (slave.attrXY <= 95) { - r += `<span class="green">XY++${V.summaryStats? `[${slave.attrXY}]`: ''}</span>`; + makeSpan(c, "XY++", "green", false, slave.attrXY); } else if (slave.attrXX > 95) { if (slave.energy <= 95) { - r += `<span class="green">Omni!</span>`; + makeSpan(c, "Omni!", "green"); } else { - r += `<span class="green">Omni+Nympho!!</span>`; + makeSpan(c, "Omni+Nympho!!", "green"); } } else { - r += `<span class="green">XY+++${V.summaryStats? `[${slave.attrXY}]`: ''}</span>`; + makeSpan(c, "XY+++", "green", false, slave.attrXY); } - r += " "; if (slave.attrXX <= 5) { - r += `<span class="red">XX---${V.summaryStats? `[${slave.attrXX}]`: ''}</span>`; + makeSpan(c, "XX---", "red", false, slave.attrXX); } else if (slave.attrXX <= 15) { - r += `<span class="red">XX--${V.summaryStats? `[${slave.attrXX}]`: ''}</span>`; + makeSpan(c, "XX--", "red", false, slave.attrXX); } else if (slave.attrXX <= 35) { - r += `<span class="red">XX-${V.summaryStats? `[${slave.attrXX}]`: ''}</span>`; + makeSpan(c, "XX-", "red", false, slave.attrXX); } else if (slave.attrXX <= 65) { - r += `XX${V.summaryStats? `[${slave.attrXX}]`: ''}`; + makeSpan(c, "XX", undefined, false, slave.attrXX); } else if (slave.attrXX <= 85) { - r += `<span class="green">XX+${V.summaryStats? `[${slave.attrXX}]`: ''}</span>`; + makeSpan(c, "XX+", "green", false, slave.attrXX); } else if (slave.attrXX <= 95) { - r += `<span class="green">XX++${V.summaryStats? `[${slave.attrXX}]`: ''}</span>`; + makeSpan(c, "XX++", "green", false, slave.attrXX); } else if (slave.attrXY <= 95) { - r += `<span class="green">XX+++${V.summaryStats? `[${slave.attrXX}]`: ''}</span>`; + makeSpan(c, "XX+++", "green", false, slave.attrXX); } - r += " "; if (slave.energy > 95) { if ((slave.attrXY <= 95) || (slave.attrXX <= 95)) { - r += `<span class="green">Nympho!</span>`; + makeSpan(c, "Nympho!", "green"); } } else if (slave.energy > 80) { - r += `<span class="green">SD++${V.summaryStats? `[${slave.energy}]`: ''}</span>`; + makeSpan(c, "SD++", "green", false, slave.energy); } else if (slave.energy > 60) { - r += `<span class="green">SD+${V.summaryStats? `[${slave.energy}]`: ''}</span>`; + makeSpan(c, "SD+", "green", false, slave.energy); } else if (slave.energy > 40) { - r += `<span class="yellow">SD${V.summaryStats? `[${slave.energy}]`: ''}</span>`; + makeSpan(c, "SD", "green", false, slave.energy); } else if (slave.energy > 20) { - r += `<span class="red">SD-${V.summaryStats? `[${slave.energy}]`: ''}</span>`; + makeSpan(c, "SD-", "red", false, slave.energy); } else { - r += `<span class="red">SD--${V.summaryStats? `[${slave.energy}]`: ''}</span>`; + makeSpan(c, "SD--", "red", false, slave.energy); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_smart_fetish(slave) { - if (slave.fetishKnown === 1) { - if (slave.clitSetting === "off") { - r += `SP-`; - } else if (((slave.fetish !== "submissive") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "submissive")) { - r += `SP:sub`; - } else if (((slave.fetish !== "cumslut") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "oral")) { - r += `SP:oral`; - } else if (((slave.fetish !== "humiliation") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "humiliation")) { - r += `SP:humil`; - } else if (((slave.fetish !== "buttslut") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "anal")) { - r += `SP:anal`; - } else if (((slave.fetish !== "boobs") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "boobs")) { - r += `SP:boobs`; - } else if (((slave.fetish !== "sadist") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "sadist")) { - r += `SP:sade`; - } else if (((slave.fetish !== "masochist") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "masochist")) { - r += `SP:pain`; - } else if (((slave.fetish !== "dom") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "dom")) { - r += `SP:dom`; - } else if (((slave.fetish !== "pregnancy") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "pregnancy")) { - r += `SP:preg`; - } else if (((slave.fetish !== "none") && (slave.clitSetting === "vanilla"))) { - r += `SP:vanilla`; - } else if ((slave.energy <= 95) && (slave.clitSetting === "all")) { - r += `SP:all`; - } else if ((slave.energy > 5) && (slave.clitSetting === "none")) { - r += `SP:none`; - } else if (!["anti-men", "anti-women", "men", "women"].includes(slave.clitSetting)) { - r += `SP:monitoring`; - } - } else { - switch (slave.clitSetting) { - case "off": - r += `SP-`; - break; - case "submissive": - r += `SP:sub`; - break; - case "lesbian": - r += `SP:les`; - break; - case "oral": - r += `SP:oral`; - break; - case "humiliation": - r += `SP:humil`; - break; - case "anal": - r += `SP:anal`; - break; - case "boobs": - r += `SP:boobs`; - break; - case "sadist": - r += `SP:sade`; - break; - case "masochist": - r += `SP:pain`; - break; - case "dom": - r += `SP:dom`; - break; - case "pregnancy": - r += `SP:pregnancy`; - break; - case "vanilla": - r += `SP:vanilla`; - break; - case "all": - r += `SP:all`; - break; - case "none": - r += `SP:none`; - break; + function short_smart_fetish(slave, c) { + function settingStr() { + if (slave.fetishKnown === 1) { + if (slave.clitSetting === "off") { + return `SP-`; + } else if (((slave.fetish !== "submissive") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "submissive")) { + return `SP:sub`; + } else if (((slave.fetish !== "cumslut") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "oral")) { + return `SP:oral`; + } else if (((slave.fetish !== "humiliation") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "humiliation")) { + return `SP:humil`; + } else if (((slave.fetish !== "buttslut") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "anal")) { + return `SP:anal`; + } else if (((slave.fetish !== "boobs") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "boobs")) { + return `SP:boobs`; + } else if (((slave.fetish !== "sadist") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "sadist")) { + return `SP:sade`; + } else if (((slave.fetish !== "masochist") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "masochist")) { + return `SP:pain`; + } else if (((slave.fetish !== "dom") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "dom")) { + return `SP:dom`; + } else if (((slave.fetish !== "pregnancy") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "pregnancy")) { + return `SP:preg`; + } else if (((slave.fetish !== "none") && (slave.clitSetting === "vanilla"))) { + return `SP:vanilla`; + } else if ((slave.energy <= 95) && (slave.clitSetting === "all")) { + return `SP:all`; + } else if ((slave.energy > 5) && (slave.clitSetting === "none")) { + return `SP:none`; + } else if (!["anti-men", "anti-women", "men", "women"].includes(slave.clitSetting)) { + return `SP:monitoring`; + } + } else { + switch (slave.clitSetting) { + case "off": + return `SP-`; + case "submissive": + return `SP:sub`; + case "lesbian": + return `SP:les`; + case "oral": + return `SP:oral`; + case "humiliation": + return `SP:humil`; + case "anal": + return `SP:anal`; + case "boobs": + return `SP:boobs`; + case "sadist": + return `SP:sade`; + case "masochist": + return `SP:pain`; + case "dom": + return `SP:dom`; + case "pregnancy": + return `SP:pregnancy`; + case "vanilla": + return `SP:vanilla`; + case "all": + return `SP:all`; + case "none": + return `SP:none`; + } } + return null; + } + const s = settingStr(); + if (s) { + makeSpan(c, settingStr()); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_smart_attraction(slave) { - if (slave.attrKnown === 1) { - if (slave.clitSetting === "women") { - if (slave.attrXX < 95) { - r += `SP:women`; - } else { - r += `SP:monitoring`; - } - } else if (slave.clitSetting === "men") { - if (slave.attrXY < 95) { - r += `SP:men`; - } else { - r += `SP:monitoring`; + function short_smart_attraction(slave, c) { + function settingStr() { + if (slave.attrKnown === 1) { + if (slave.clitSetting === "women") { + if (slave.attrXX < 95) { + return `SP:women`; + } else { + return `SP:monitoring`; + } + } else if (slave.clitSetting === "men") { + if (slave.attrXY < 95) { + return `SP:men`; + } else { + return `SP:monitoring`; + } + } else if (slave.clitSetting === "anti-women") { + if (slave.attrXX > 0) { + return `SP:anti-women`; + } else { + return `SP:monitoring`; + } + } else if (slave.clitSetting === "anti-men") { + if (slave.attrXY > 0) { + return `SP:anti-men`; + } else { + return `SP:monitoring`; + } } - } else if (slave.clitSetting === "anti-women") { - if (slave.attrXX > 0) { - r += `SP:anti-women`; - } else { - r += `SP:monitoring`; - } - } else if (slave.clitSetting === "anti-men") { - if (slave.attrXY > 0) { - r += `SP:anti-men`; - } else { - r += `SP:monitoring`; + } else { + if (slave.clitSetting === "women") { + return `SP:women`; + } else if (slave.clitSetting === "men") { + return `SP:men`; + } else if (slave.clitSetting === "anti-women") { + return `SP:anti-women`; + } else if (slave.clitSetting === "anti-men") { + return `SP:anti-men`; } } - } else { - if (slave.clitSetting === "women") { - r += `SP:women`; - } else if (slave.clitSetting === "men") { - r += `SP:men`; - } else if (slave.clitSetting === "anti-women") { - r += `SP:anti-women`; - } else if (slave.clitSetting === "anti-men") { - r += `SP:anti-men`; - } + return null; + } + const s = settingStr(); + if (s) { + makeSpan(c, settingStr()); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_behavior_flaw(slave) { - r += `<span class="red">`; - switch (slave.behavioralFlaw) { - case "arrogant": - r += `Arrog`; - break; - case "bitchy": - r += `Bitchy`; - break; - case "odd": - r += `Odd`; - break; - case "hates men": - r += `Men-`; - break; - case "hates women": - r += `Women-`; - break; - case "gluttonous": - r += `Glut`; - break; - case "anorexic": - r += `Ano`; - break; - case "devout": - r += `Dev`; - break; - case "liberated": - r += `Lib`; - break; - default: - slave.behavioralFlaw = "none"; - break; + function short_behavior_flaw(slave, c) { + function descStr() { + switch (slave.behavioralFlaw) { + case "arrogant": + return `Arrog`; + case "bitchy": + return `Bitchy`; + case "odd": + return `Odd`; + case "hates men": + return `Men-`; + case "hates women": + return `Women-`; + case "gluttonous": + return `Glut`; + case "anorexic": + return `Ano`; + case "devout": + return `Dev`; + case "liberated": + return `Lib`; + default: + slave.behavioralFlaw = "none"; + return null; + } + } + const s = descStr(); + if (s) { + makeSpan(c, descStr(), "red"); } - r += `</span> `; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_sex_flaw(slave) { + function short_sex_flaw(slave, c) { switch (slave.sexualFlaw) { case "hates oral": - r += `<span class="red">Oral-</span>`; + makeSpan(c, "Oral-", "red"); break; case "hates anal": - r += `<span class="red">Anal-</span>`; + makeSpan(c, "Anal-", "red"); break; case "hates penetration": - r += `<span class="red">Fuck-</span>`; + makeSpan(c, "Fuck-", "red"); break; case "shamefast": - r += `<span class="red">Shame</span>`; + makeSpan(c, "Shame", "red"); break; case "idealistic": - r += `<span class="red">Ideal</span>`; + makeSpan(c, "Ideal", "red"); break; case "repressed": - r += `<span class="red">Repre</span>`; + makeSpan(c, "Repre", "red"); break; case "apathetic": - r += `<span class="red">Apath</span>`; + makeSpan(c, "Apath", "red"); break; case "crude": - r += `<span class="red">Crude</span>`; + makeSpan(c, "Crude", "red"); break; case "judgemental": - r += `<span class="red">Judge</span>`; + makeSpan(c, "Judge", "red"); break; case "cum addict": - r += `<span class="yellow">CumAdd</span>`; + makeSpan(c, "CumAdd", "yellow"); break; case "anal addict": - r += `<span class="yellow">AnalAdd</span>`; + makeSpan(c, "AnalAdd", "yellow"); break; case "attention whore": - r += `<span class="yellow">Attention</span>`; + makeSpan(c, "Attention", "yellow"); break; case "breast growth": - r += `<span class="yellow">BoobObsess</span>`; + makeSpan(c, "BoobObsess", "yellow"); break; case "abusive": - r += `<span class="yellow">Abusive</span>`; + makeSpan(c, "Abusive", "yellow"); break; case "malicious": - r += `<span class="yellow">Malice</span>`; + makeSpan(c, "Malice", "yellow"); break; case "self hating": - r += `<span class="yellow">SelfHatr</span>`; + makeSpan(c, "SelfHatr", "yellow"); break; case "neglectful": - r += `<span class="yellow">SelfNeglect</span>`; + makeSpan(c, "SelfNeglect", "yellow"); break; case "breeder": - r += `<span class="yellow">BreedObsess</span>`; + makeSpan(c, "BreedObsess", "yellow"); break; default: slave.sexualFlaw = "none"; break; } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_behavior_quirk(slave) { - r += `<span class="green">`; - switch (slave.behavioralQuirk) { - case "confident": - r += `Confid`; - break; - case "cutting": - r += `Cutting`; - break; - case "funny": - r += `Funny`; - break; - case "fitness": - r += `Fit`; - break; - case "adores women": - r += `Women+`; - break; - case "adores men": - r += `Men+`; - break; - case "insecure": - r += `Insec`; - break; - case "sinful": - r += `Sinf`; - break; - case "advocate": - r += `Advoc`; - break; - default: - slave.behavioralQuirk = "none"; - break; + function short_behavior_quirk(slave, c) { + function descStr() { + switch (slave.behavioralQuirk) { + case "confident": + return `Confid`; + case "cutting": + return `Cutting`; + case "funny": + return `Funny`; + case "fitness": + return `Fit`; + case "adores women": + return `Women+`; + case "adores men": + return `Men+`; + case "insecure": + return `Insec`; + case "sinful": + return `Sinf`; + case "advocate": + return `Advoc`; + default: + slave.behavioralQuirk = "none"; + return null; + } + } + const s = descStr(); + if (s) { + makeSpan(c, s, "green"); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_sex_quirk(slave) { - switch (slave.sexualQuirk) { - case "gagfuck queen": - r += `Gagfuck`; - break; - case "painal queen": - r += `Painal`; - break; - case "strugglefuck queen": - r += `Struggle`; - break; - case "tease": - r += `Tease`; - break; - case "romantic": - r += `Romantic`; - break; - case "perverted": - r += `Perverted`; - break; - case "caring": - r += `Caring`; - break; - case "unflinching": - r += `Unflinch`; - break; - case "size queen": - r += `SizeQ`; - break; - default: - slave.sexualQuirk = "none"; - break; + function short_sex_quirk(slave, c) { + function descStr() { + switch (slave.sexualQuirk) { + case "gagfuck queen": + return `Gagfuck`; + case "painal queen": + return `Painal`; + case "strugglefuck queen": + return `Struggle`; + case "tease": + return `Tease`; + case "romantic": + return `Romantic`; + case "perverted": + return `Perverted`; + case "caring": + return `Caring`; + case "unflinching": + return `Unflinch`; + case "size queen": + return `SizeQ`; + default: + slave.sexualQuirk = "none"; + return null; + } + } + const s = descStr(); + if (s) { + makeSpan(c, s, "green"); } - r += `</span> `; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_fetish(slave) { - r += `<span class="lightcoral">`; - switch (slave.fetish) { - case "submissive": - if (slave.fetishStrength > 95) { - r += `Complete submissive${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } else if (slave.fetishStrength > 60) { - r += `Submissive${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } else { - r += `Submissive tendencies${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } - break; - case "cumslut": - if (slave.fetishStrength > 95) { - r += `Cumslut${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } else if (slave.fetishStrength > 60) { - r += `Oral fixation${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } else { - r += `Prefers oral${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } - break; - case "humiliation": - if (slave.fetishStrength > 95) { - r += `Humiliation slut${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } else if (slave.fetishStrength > 60) { - r += `Exhibitionist${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } else { - r += `Interest in humiliation${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } - break; - case "buttslut": - if (slave.fetishStrength > 95) { - r += `Buttslut${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } else if (slave.fetishStrength > 60) { - r += `Anal fixation${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } else { - r += `Prefers anal${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } - break; - case "boobs": - if (slave.fetishStrength > 95) { - r += `Boobslut${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } else if (slave.fetishStrength > 60) { - r += `Breast fixation${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } else { - r += `Loves boobs${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } - break; - case "sadist": - if (slave.fetishStrength > 95) { - r += `Complete sadist${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } else if (slave.fetishStrength > 60) { - r += `Sadist${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } else { - r += `Sadistic tendencies${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } - break; - case "masochist": - if (slave.fetishStrength > 95) { - r += `Complete masochist${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } else if (slave.fetishStrength > 60) { - r += `Masochist${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } else { - r += `Masochistic tendencies${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } - break; - case "dom": - if (slave.fetishStrength > 95) { - r += `Complete dom${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } else if (slave.fetishStrength > 60) { - r += `Dominant${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } else { - r += `Dominant tendencies${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } - break; - case "pregnancy": - if (slave.fetishStrength > 95) { - r += `Pregnancy fetish${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } else if (slave.fetishStrength > 60) { - r += `Pregnancy kink${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } else { - r += `Interest in impregnation${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - } - break; - default: - r += `Sexually vanilla${V.summaryStats? `[${slave.fetishStrength}]` : ''}.`; - break; + function long_fetish(slave, c) { + function fetishStr() { + switch (slave.fetish) { + case "submissive": + if (slave.fetishStrength > 95) { + return "Complete submissive"; + } else if (slave.fetishStrength > 60) { + return "Submissive"; + } else { + return "Submissive tendencies"; + } + case "cumslut": + if (slave.fetishStrength > 95) { + return "Cumslut"; + } else if (slave.fetishStrength > 60) { + return "Oral fixation"; + } else { + return "Prefers oral"; + } + case "humiliation": + if (slave.fetishStrength > 95) { + return "Humiliation slut"; + } else if (slave.fetishStrength > 60) { + return "Exhibitionist"; + } else { + return "Interest in humiliation"; + } + case "buttslut": + if (slave.fetishStrength > 95) { + return "Buttslut"; + } else if (slave.fetishStrength > 60) { + return "Anal fixation"; + } else { + return "Prefers anal"; + } + case "boobs": + if (slave.fetishStrength > 95) { + return "Boobslut"; + } else if (slave.fetishStrength > 60) { + return "Breast fixation"; + } else { + return "Loves boobs"; + } + case "sadist": + if (slave.fetishStrength > 95) { + return "Complete sadist"; + } else if (slave.fetishStrength > 60) { + return "Sadist"; + } else { + return "Sadistic tendencies"; + } + case "masochist": + if (slave.fetishStrength > 95) { + return "Complete masochist"; + } else if (slave.fetishStrength > 60) { + return "Masochist"; + } else { + return "Masochistic tendencies"; + } + case "dom": + if (slave.fetishStrength > 95) { + return "Complete dom"; + } else if (slave.fetishStrength > 60) { + return "Dominant"; + } else { + return "Dominant tendencies"; + } + case "pregnancy": + if (slave.fetishStrength > 95) { + return "Pregnancy fetish"; + } else if (slave.fetishStrength > 60) { + return "Pregnancy kink"; + } else { + return "Interest in impregnation"; + } + default: + return "Sexually vanilla"; + } } - r += `</span> `; + makeSpan(c, fetishStr(), "lightcoral", true, slave.fetishStrength); } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_attraction(slave) { + function long_attraction(slave, c) { if (slave.attrXY <= 5) { - r += `<span class="red">Disgusted by men${V.summaryStats? `[${slave.attrXY}]` : ''},</span> `; + makeSpan(c, "Disgusted by men", "red", true, slave.attrXY); } else if (slave.attrXY <= 15) { - r += `<span class="red">Turned off by men${V.summaryStats? `[${slave.attrXY}]` : ''},</span> `; + makeSpan(c, "Turned off by men", "red", true, slave.attrXY); } else if (slave.attrXY <= 35) { - r += `<span class="red">Not attracted to men${V.summaryStats? `[${slave.attrXY}]` : ''},</span> `; + makeSpan(c, "Not attracted to men", "red", true, slave.attrXY); } else if (slave.attrXY <= 65) { - r += `Indifferent to men${V.summaryStats? `[${slave.attrXY}]` : ''}, `; + makeSpan(c, "Indifferent to men", undefined, true, slave.attrXY); } else if (slave.attrXY <= 85) { - r += `<span class="green">Attracted to men${V.summaryStats? `[${slave.attrXY}]` : ''},</span> `; + makeSpan(c, "Attracted to men", "green", true, slave.attrXY); } else if (slave.attrXY <= 95) { - r += `<span class="green">Aroused by men${V.summaryStats? `[${slave.attrXY}]` : ''},</span> `; + makeSpan(c, "Aroused by men", "green", true, slave.attrXY); } else if (slave.attrXX > 95) { if (slave.energy <= 95) { - r += `<span class="green">Omnisexual!</span> `; + makeSpan(c, "Omnisexual!", "green"); } else { - r += `<span class="green">Omnisexual nymphomaniac!</span> `; + makeSpan(c, "Omnisexual nymphomaniac!", "green"); } } else { - r += `<span class="green">Passionate about men${V.summaryStats? `[${slave.attrXY}]` : ''},</span> `; + makeSpan(c, "Passionate about men", "green", true, slave.attrXY); } if (slave.attrXX <= 5) { - r += `<span class="red">disgusted by women${V.summaryStats? `[${slave.attrXX}]` : ''}.</span> `; + makeSpan(c, "disgusted by women", "red", true, slave.attrXX); } else if (slave.attrXX <= 15) { - r += `<span class="red">turned off by women${V.summaryStats? `[${slave.attrXX}]` : ''}.</span> `; + makeSpan(c, "turned off by women", "red", true, slave.attrXX); } else if (slave.attrXX <= 35) { - r += `<span class="red">not attracted to women${V.summaryStats? `[${slave.attrXX}]` : ''}.</span> `; + makeSpan(c, "not attracted to women", "red", true, slave.attrXX); } else if (slave.attrXX <= 65) { - r += `indifferent to women${V.summaryStats? `[${slave.attrXX}]` : ''}. `; + makeSpan(c, "Disgusted by women", undefined, true, slave.attrXX); } else if (slave.attrXX <= 85) { - r += `<span class="green">attracted to women${V.summaryStats? `[${slave.attrXX}]` : ''}.</span> `; + makeSpan(c, "attracted to women", "green", true, slave.attrXX); } else if (slave.attrXX <= 95) { - r += `<span class="green">aroused by women${V.summaryStats? `[${slave.attrXX}]` : ''}.</span> `; + makeSpan(c, "aroused by women", "green", true, slave.attrXX); } else if (slave.attrXY <= 95) { - r += `<span class="green">passionate about women${V.summaryStats? `[${slave.attrXX}]` : ''}.</span> `; + makeSpan(c, "passionate about women", "green", true, slave.attrXX); } if (slave.energy > 95) { if ((slave.attrXY <= 95) || (slave.attrXX <= 95)) { - r += `<span class="green">Nymphomaniac!</span>`; + makeSpan(c, "Nymphomaniac!", "green"); } } else if (slave.energy > 80) { - r += `<span class="green">Powerful sex drive${V.summaryStats? `[${slave.energy}]` : ''}.</span>`; + makeSpan(c, "Powerful sex drive", "green", true, slave.energy); } else if (slave.energy > 60) { - r += `<span class="green">Good sex drive${V.summaryStats? `[${slave.energy}]` : ''}.</span>`; + makeSpan(c, "Good sex drive", "green", true, slave.energy); } else if (slave.energy > 40) { - r += `<span class="yellow">Average sex drive${V.summaryStats? `[${slave.energy}]` : ''}.</span>`; + makeSpan(c, "Average sex drive", "yellow", true, slave.energy); } else if (slave.energy > 20) { - r += `<span class="red">Poor sex drive${V.summaryStats? `[${slave.energy}]` : ''}.</span>`; + makeSpan(c, "Poor sex drive", "red", true, slave.energy); } else { - r += `<span class="red">No sex drive${V.summaryStats? `[${slave.energy}]` : ''}.</span>`; + makeSpan(c, "No sex drive", "red", true, slave.energy); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_smart_fetish(slave) { - if (slave.fetishKnown === 1) { - if (slave.clitSetting === "off") { - r += `SP off.`; - } else if (((slave.fetish !== "submissive") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "submissive")) { - r += `SP: submissive.`; - } else if (((slave.fetish !== "cumslut") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "oral")) { - r += `SP: oral.`; - } else if (((slave.fetish !== "humiliation") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "humiliation")) { - r += `SP: humiliation.`; - } else if (((slave.fetish !== "buttslut") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "anal")) { - r += `SP: anal.`; - } else if (((slave.fetish !== "boobs") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "boobs")) { - r += `SP: breasts.`; - } else if (((slave.fetish !== "sadist") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "sadist")) { - r += `SP: sadism.`; - } else if (((slave.fetish !== "masochist") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "masochist")) { - r += `SP: masochism.`; - } else if (((slave.fetish !== "dom") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "dom")) { - r += `SP: dominance.`; - } else if (((slave.fetish !== "pregnancy") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "pregnancy")) { - r += `SP: pregnancy.`; - } else if ((slave.fetish !== "none") && (slave.clitSetting === "vanilla")) { - r += `SP: vanilla.`; - } else if ((slave.energy <= 95) && (slave.clitSetting === "all")) { - r += `SP: all.`; - } else if ((slave.energy > 5) && (slave.clitSetting === "none")) { - r += `SP: none.`; - } else if (!["anti-men", "anti-women", "men", "women"].includes(slave.clitSetting)) { - r += `SP: monitoring.`; - } - } else { - switch (slave.clitSetting) { - case "off": - r += `SP off.`; - break; - case "submissive": - r += `SP: submissive.`; - break; - case "oral": - r += `SP: oral.`; - break; - case "humiliation": - r += `SP: humiliation.`; - break; - case "anal": - r += `SP: anal.`; - break; - case "boobs": - r += `SP: breasts.`; - break; - case "sadist": - r += `SP: sadism.`; - break; - case "masochist": - r += `SP: masochism.`; - break; - case "dom": - r += `SP: dominance.`; - break; - case "pregnancy": - r += `SP: pregnancy.`; - break; - case "vanilla": - r += `SP: vanilla.`; - break; - case "all": - r += `SP: all.`; - break; - case "none": - r += `SP: none.`; - break; + function long_smart_fetish(slave, c) { + function descStr() { + if (slave.fetishKnown === 1) { + if (slave.clitSetting === "off") { + return `SP off.`; + } else if (((slave.fetish !== "submissive") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "submissive")) { + return `SP: submissive.`; + } else if (((slave.fetish !== "cumslut") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "oral")) { + return `SP: oral.`; + } else if (((slave.fetish !== "humiliation") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "humiliation")) { + return `SP: humiliation.`; + } else if (((slave.fetish !== "buttslut") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "anal")) { + return `SP: anal.`; + } else if (((slave.fetish !== "boobs") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "boobs")) { + return `SP: breasts.`; + } else if (((slave.fetish !== "sadist") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "sadist")) { + return `SP: sadism.`; + } else if (((slave.fetish !== "masochist") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "masochist")) { + return `SP: masochism.`; + } else if (((slave.fetish !== "dom") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "dom")) { + return `SP: dominance.`; + } else if (((slave.fetish !== "pregnancy") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "pregnancy")) { + return `SP: pregnancy.`; + } else if ((slave.fetish !== "none") && (slave.clitSetting === "vanilla")) { + return `SP: vanilla.`; + } else if ((slave.energy <= 95) && (slave.clitSetting === "all")) { + return `SP: all.`; + } else if ((slave.energy > 5) && (slave.clitSetting === "none")) { + return `SP: none.`; + } else if (!["anti-men", "anti-women", "men", "women"].includes(slave.clitSetting)) { + return `SP: monitoring.`; + } + } else { + switch (slave.clitSetting) { + case "off": + return `SP off.`; + case "submissive": + return `SP: submissive.`; + case "oral": + return `SP: oral.`; + case "humiliation": + return `SP: humiliation.`; + case "anal": + return `SP: anal.`; + case "boobs": + return `SP: breasts.`; + case "sadist": + return `SP: sadism.`; + case "masochist": + return `SP: masochism.`; + case "dom": + return `SP: dominance.`; + case "pregnancy": + return `SP: pregnancy.`; + case "vanilla": + return `SP: vanilla.`; + case "all": + return `SP: all.`; + case "none": + return `SP: none.`; + } } + return null; + } + const s = descStr(); + if (s) { + makeSpan(c, s); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_smart_attraction(slave) { + function long_smart_attraction(slave, c) { if (slave.attrKnown === 1) { if ((slave.attrXX < 100) && (slave.clitSetting === "women")) { - r += `SP: women.`; + makeSpan(c, `SP: women.`); } else if ((slave.attrXY < 100) && (slave.clitSetting === "men")) { - r += `SP: men.`; + makeSpan(c, `SP: men.`); } } else { if (slave.clitSetting === "women") { - r += `SP: women.`; + makeSpan(c, `SP: women.`); } else if (slave.clitSetting === "men") { - r += `SP: men.`; + makeSpan(c, `SP: men.`); } } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_behavior_flaw(slave) { - r += `<span class="red">`; - switch (slave.behavioralFlaw) { - case "arrogant": - r += `Arrogant.`; - break; - case "bitchy": - r += `Bitchy.`; - break; - case "odd": - r += `Odd.`; - break; - case "hates men": - r += `Hates men.`; - break; - case "hates women": - r += `Hates women.`; - break; - case "gluttonous": - r += `Stress eater.`; - break; - case "anorexic": - r += `Anorexic.`; - break; - case "devout": - r += `Devoutly religious.`; - break; - case "liberated": - r += `Mentally liberated.`; - break; - default: - slave.behavioralFlaw = "none"; - break; + function long_behavior_flaw(slave, c) { + function descStr() { + switch (slave.behavioralFlaw) { + case "arrogant": + return `Arrogant.`; + case "bitchy": + return `Bitchy.`; + case "odd": + return `Odd.`; + case "hates men": + return `Hates men.`; + case "hates women": + return `Hates women.`; + case "gluttonous": + return `Stress eater.`; + case "anorexic": + return `Anorexic.`; + case "devout": + return `Devoutly religious.`; + case "liberated": + return `Mentally liberated.`; + default: + slave.behavioralFlaw = "none"; + return null; + } + } + const s = descStr(); + if (s) { + makeSpan(c, s, "red"); } - r += `</span> `; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_sex_flaw(slave) { + function long_sex_flaw(slave, c) { switch (slave.sexualFlaw) { case "hates oral": - r += `<span class="red">Hates oral.</span>`; - break; case "hates anal": - r += `<span class="red">Hates anal.</span>`; - break; case "hates penetration": - r += `<span class="red">Hates penetration.</span>`; - break; case "shamefast": - r += `<span class="red">Shamefast.</span>`; + makeSpan(c, slave.sexualFlaw, "red", true); break; case "idealistic": - r += `<span class="red">Sexually idealistic.</span>`; - break; case "repressed": - r += `<span class="red">Sexually repressed.</span>`; - break; case "apathetic": - r += `<span class="red">Sexually apathetic.</span>`; - break; case "crude": - r += `<span class="red">Sexually crude.</span>`; - break; case "judgemental": - r += `<span class="red">Sexually judgemental.</span>`; + makeSpan(c, `Sexually ${slave.sexualFlaw}.`, "red"); break; case "cum addict": - r += `<span class="yellow">Cum addict.</span>`; - break; case "anal addict": - r += `<span class="yellow">Anal addict.</span>`; - break; case "attention whore": - r += `<span class="yellow">Attention whore.</span>`; + makeSpan(c, slave.sexualFlaw, "yellow", true); break; case "breast growth": - r += `<span class="yellow">Breast obsession.</span>`; + makeSpan(c, `Breast obsession.`, "yellow"); break; case "abusive": - r += `<span class="yellow">Sexually abusive.</span>`; - break; case "malicious": - r += `<span class="yellow">Sexually malicious.</span>`; + makeSpan(c, `Sexually ${slave.sexualFlaw}.`, "yellow"); break; case "self hating": - r += `<span class="yellow">Self hatred.</span>`; + makeSpan(c, `Self hatred.`, "yellow"); break; case "neglectful": - r += `<span class="yellow">Self neglectful.</span>`; + makeSpan(c, `Self neglectful.`, "yellow"); break; case "breeder": - r += `<span class="yellow">Breeding obsession.</span>`; + makeSpan(c, `Breeding obsession.`, "yellow"); break; default: slave.sexualFlaw = "none"; break; } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_behavior_quirk(slave) { - r += `<span class="green">`; + function long_behavior_quirk(slave, c) { switch (slave.behavioralQuirk) { case "confident": - r += `Confident.`; - break; case "cutting": - r += `Cutting.`; - break; case "funny": - r += `Funny.`; - break; case "fitness": - r += `Fitness.`; - break; case "adores women": - r += `Adores women.`; - break; case "adores men": - r += `Adores men.`; - break; case "insecure": - r += `Insecure.`; - break; case "sinful": - r += `Sinful.`; - break; case "advocate": - r += `Advocate.`; + makeSpan(c, slave.behavioralQuirk, "green", true); break; default: slave.behavioralQuirk = "none"; break; } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_sex_quirk(slave) { + function long_sex_quirk(slave, c) { switch (slave.sexualQuirk) { case "gagfuck queen": - r += `Gagfuck queen.`; - break; case "painal queen": - r += `Painal queen.`; - break; case "strugglefuck queen": - r += `Strugglefuck queen.`; - break; case "tease": - r += `Tease.`; - break; case "romantic": - r += `Romantic.`; - break; case "perverted": - r += `Perverted.`; - break; case "caring": - r += `Caring.`; - break; case "unflinching": - r += `Unflinching.`; - break; case "size queen": - r += `Size queen.`; + makeSpan(c, slave.sexualQuirk, "green", true); break; default: slave.sexualQuirk = "none"; break; } - r += `</span> `; } /** * @param {App.Entity.SlaveState} slave + * @returns {string} */ function short_extended_family(slave) { + let res = ""; let handled = 0; if (slave.mother > 0) { const _ssj = V.slaves.findIndex(s => s.ID === slave.mother); if (_ssj !== -1) { - r += `${SlaveFullName(V.slaves[_ssj])}'s ${getPronouns(slave).daughter}`; + res += `${SlaveFullName(V.slaves[_ssj])}'s ${getPronouns(slave).daughter}`; if (slave.relationshipTarget === V.slaves[_ssj].ID) { const friendShipShort = relationshipTermShort(slave); - r += ` & ${friendShipShort}`; + res += ` & ${friendShipShort}`; handled = 1; } } - r += " "; + res += " "; } else if (slave.mother === -1) { - r += `Your ${getPronouns(slave).daughter}`; + res += `Your ${getPronouns(slave).daughter}`; if (slave.relationship === -3) { - r += ` & wife`; + res += ` & wife`; handled = 1; } else if (slave.relationship === -2) { - r += ` & lover`; + res += ` & lover`; handled = 1; } - r += " "; + res += " "; } else if (slave.mother in V.missingTable && V.showMissingSlavesSD && V.showMissingSlaves) { - r += `${V.missingTable[slave.mother].fullName}'s ${getPronouns(slave).daughter} `; + res += `${V.missingTable[slave.mother].fullName}'s ${getPronouns(slave).daughter} `; } if (slave.father > 0 && slave.father !== slave.mother) { const _ssj = V.slaves.findIndex(s => s.ID === slave.father); if (_ssj !== -1) { - r += `${SlaveFullName(V.slaves[_ssj])}'s ${getPronouns(slave).daughter}`; + res += `${SlaveFullName(V.slaves[_ssj])}'s ${getPronouns(slave).daughter}`; if (slave.relationshipTarget === V.slaves[_ssj].ID && handled !== 1) { const friendShipShort = relationshipTermShort(slave); - r += ` & ${friendShipShort}`; + res += ` & ${friendShipShort}`; handled = 1; } } - r += " "; + res += " "; } else if (slave.father === -1 && slave.mother !== -1) { - r += `Your ${getPronouns(slave).daughter}`; + res += `Your ${getPronouns(slave).daughter}`; if (slave.relationship === -3) { - r += ` & wife`; + res += ` & wife`; handled = 1; } else if (slave.relationship === -2) { - r += ` & lover`; + res += ` & lover`; handled = 1; } - r += " "; + res += " "; } else if (slave.father in V.missingTable && slave.father !== slave.mother && V.showMissingSlavesSD && V.showMissingSlaves) { - r += `${V.missingTable[slave.father].fullName}'s ${getPronouns(slave).daughter}`; + res += `${V.missingTable[slave.father].fullName}'s ${getPronouns(slave).daughter}`; } if (slave.daughters === 1) { let _ssj = V.slaves.findIndex(s => s.mother === slave.ID); if (_ssj !== -1) { - r += `${SlaveFullName(V.slaves[_ssj])}'s mother`; + res += `${SlaveFullName(V.slaves[_ssj])}'s mother`; if (slave.relationshipTarget === V.slaves[_ssj].ID) { const friendShipShort = relationshipTermShort(slave); - r += ` & ${friendShipShort}`; + res += ` & ${friendShipShort}`; handled = 1; } } - r += " "; + res += " "; _ssj = V.slaves.findIndex(s => s.father === slave.ID); if (_ssj !== -1) { - r += `${SlaveFullName(V.slaves[_ssj])}'s father`; + res += `${SlaveFullName(V.slaves[_ssj])}'s father`; if (slave.relationshipTarget === V.slaves[_ssj].ID && handled !== 1) { const friendShipShort = relationshipTermShort(slave); - r += ` & ${friendShipShort}`; + res += ` & ${friendShipShort}`; handled = 1; } } - r += " "; + res += " "; } else if (slave.daughters > 1) { - r += `multiple daughters `; + res += `multiple daughters `; } if (slave.sisters === 1) { const _ssj = V.slaves.findIndex(s => areSisters(s, slave) > 0); if (_ssj !== -1) { - r += `${SlaveFullName(V.slaves[_ssj])}'s ${getPronouns(slave).sister}`; + res += `${SlaveFullName(V.slaves[_ssj])}'s ${getPronouns(slave).sister}`; if (slave.relationshipTarget === V.slaves[_ssj].ID) { const friendShipShort = relationshipTermShort(slave); - r += `& ${friendShipShort}`; + res += `& ${friendShipShort}`; handled = 1; } } - r += " "; + res += " "; } else if (slave.sisters > 1) { - r += `multiple sisters `; + res += `multiple sisters `; } if (slave.relationship > 0 && handled !== 1) { const _ssj = V.slaves.findIndex(s => s.ID === slave.relationshipTarget); if (_ssj !== -1) { - r += `${SlaveFullName(V.slaves[_ssj])}'s`; + res += `${SlaveFullName(V.slaves[_ssj])}'s`; const friendShipShort = relationshipTermShort(slave); - r += ` ${friendShipShort}`; + res += ` ${friendShipShort}`; } } else if (slave.relationship === -3 && slave.mother !== -1 && slave.father !== -1) { - r += `Your wife`; + res += `Your wife`; } else if (slave.relationship === -2) { - r += `E Bonded`; + res += `E Bonded`; } else if (slave.relationship === -1) { - r += `E Slut`; + res += `E Slut`; } - r += " "; + return res; } /** * @param {App.Entity.SlaveState} slave + * @returns {string} */ function short_legacy_family(slave) { + let res = ""; if (slave.relation !== 0) { const _ssj = V.slaves.findIndex(s => s.ID === slave.relationTarget); if (_ssj !== -1) { - r += `${SlaveFullName(V.slaves[_ssj])}'s ${slave.relation}`; + res += `${SlaveFullName(V.slaves[_ssj])}'s ${slave.relation}`; } } if (slave.relationship > 0) { @@ -4106,187 +3769,204 @@ window.SlaveSummaryUncached = (function() { if (_ssj !== -1) { const friendship = relationshipTerm(slave); if (slave.relationshipTarget !== slave.relationTarget) { - r += `${SlaveFullName(V.slaves[_ssj])}'s`; + res += `${SlaveFullName(V.slaves[_ssj])}'s`; } else { - r += ` &`; + res += ` &`; } - r += ` ${friendship}`; + res += ` ${friendship}`; } } else if (slave.relationship === -3) { - r += `Your wife`; + res += `Your wife`; } else if (slave.relationship === -2) { - r += `E Bonded`; + res += `E Bonded`; } else if (slave.relationship === -1) { - r += `E Slut`; + res += `E Slut`; } + return res; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_clone(slave) { + function short_clone(slave, c) { if (slave.clone !== 0) { - r += ` Clone`; + makeSpan(c, "Clone"); } } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function short_rival(slave) { + function short_rival(slave, c) { if (slave.rivalry !== 0) { - r += ` `; + const block = makeBlock(c, "lightsalmon"); const _ssj = V.slaves.findIndex(s => s.ID === slave.rivalryTarget); if (_ssj !== -1) { - r += `<span class="lightsalmon">`; if (slave.rivalry <= 1) { - r += `Disl ${SlaveFullName(V.slaves[_ssj])}`; + block.textContent = `Disl ${SlaveFullName(V.slaves[_ssj])}`; } else if (slave.rivalry <= 2) { - r += `${SlaveFullName(V.slaves[_ssj])}'s rival`; + block.textContent = `${SlaveFullName(V.slaves[_ssj])}'s rival`; } else { - r += `Hates ${SlaveFullName(V.slaves[_ssj])}`; + block.textContent = `Hates ${SlaveFullName(V.slaves[_ssj])}`; } - r += `</span> `; } } } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_extended_family(slave) { + function long_extended_family(slave, c) { let handled = 0; + const block = makeBlock(); if (slave.mother > 0) { const _ssj = V.slaves.findIndex(s => s.ID === slave.mother); if (_ssj !== -1) { - r += `${SlaveFullName(V.slaves[_ssj])}'s <span class="lightgreen">${getPronouns(slave).daughter}`; + addText(block, `${SlaveFullName(V.slaves[_ssj])}'s `); + const tmpSpan = makeSpan(block, getPronouns(slave).daughter, "lightgreen"); if (slave.relationshipTarget === V.slaves[_ssj].ID) { const friendShipShort = relationshipTerm(slave); - r += ` and ${friendShipShort}`; + tmpSpan.textContent += ` and ${friendShipShort}`; handled = 1; } - r += `.</span> `; + tmpSpan.textContent += '.'; } } else if (slave.mother === -1) { - r += `Your `; + addText(block, `Your `); if (slave.relationship === -3) { - r += `<span class="lightgreen">${getPronouns(slave).daughter} and wife.</span> `; + makeSpan(block, `${getPronouns(slave).daughter} and wife.`, "lightgreen"); handled = 1; } else if (slave.relationship === -2) { - r += `<span class="lightgreen">${getPronouns(slave).daughter} and lover.</span> `; + makeSpan(block, `${getPronouns(slave).daughter} and lover.`, "lightgreen"); handled = 1; } else { - r += `<span class="lightgreen">${getPronouns(slave).daughter}.</span> `; + makeSpan(block, `${getPronouns(slave).daughter}.`, "lightgreen"); } } else if (slave.mother in V.missingTable && V.showMissingSlavesSD && V.showMissingSlaves) { - r += `${V.missingTable[slave.mother].fullName}'s <span class="lightgreen">${getPronouns(slave).daughter}.</span> `; + addText(block, `${V.missingTable[slave.mother].fullName}'s `); + makeSpan(block, `${getPronouns(slave).daughter}.`, "lightgreen"); } if (slave.father > 0 && slave.father !== slave.mother) { const _ssj = V.slaves.findIndex(s => s.ID === slave.father); if (_ssj !== -1) { - r += `${SlaveFullName(V.slaves[_ssj])}'s <span class="lightgreen">${getPronouns(slave).daughter}`; + addText(block, `${SlaveFullName(V.slaves[_ssj])}'s `); + const tmpSpan = makeSpan(block, getPronouns(slave).daughter, "lightgreen"); if (slave.relationshipTarget === V.slaves[_ssj].ID) { const friendShipShort = relationshipTerm(slave); - r += ` and ${friendShipShort}`; + tmpSpan.textContent += ` and ${friendShipShort}`; handled = 1; } - r += `.</span> `; + tmpSpan.textContent += '.'; } } else if (slave.father === -1 && slave.father !== slave.mother) { - r += `Your `; + addText(block, `Your `); if (slave.relationship === -3) { - r += `<span class="lightgreen">${getPronouns(slave).daughter} and wife.</span> `; + makeSpan(block, `${getPronouns(slave).daughter} and wife.`, "lightgreen"); handled = 1; } else if (slave.relationship === -2) { - r += `<span class="lightgreen">${getPronouns(slave).daughter} and lover.</span> `; + makeSpan(block, `${getPronouns(slave).daughter} and lover.`, "lightgreen"); handled = 1; } else { - r += `<span class="lightgreen">${getPronouns(slave).daughter}.</span> `; + makeSpan(block, `${getPronouns(slave).daughter}.`, "lightgreen"); } } else if (slave.father in V.missingTable && slave.father !== slave.mother && V.showMissingSlavesSD && V.showMissingSlaves) { - r += `${V.missingTable[slave.father].fullName}'s <span class="lightgreen">${getPronouns(slave).daughter}.</span> `; + addText(block, `${V.missingTable[slave.mother].fullName}'s `); + makeSpan(block, `${getPronouns(slave).daughter}.`, "lightgreen"); } if (slave.daughters === 1) { let _ssj = V.slaves.findIndex(s => s.mother === slave.ID); if (_ssj !== -1) { - r += `${SlaveFullName(V.slaves[_ssj])}'s <span class="lightgreen">mother`; + addText(block, `${SlaveFullName(V.slaves[_ssj])}'s `); + const tmpSpan = makeSpan(block, "mother", "lightgreen"); if (slave.relationshipTarget === V.slaves[_ssj].ID) { const friendShipShort = relationshipTerm(slave); - r += ` and ${friendShipShort}`; + tmpSpan.textContent += ` and ${friendShipShort}`; handled = 1; } - r += `.</span> `; + tmpSpan.textContent += '.'; } _ssj = V.slaves.findIndex(s => s.father === slave.ID); if (_ssj !== -1) { - r += `${SlaveFullName(V.slaves[_ssj])}'s <span class="lightgreen">father`; + addText(block, `${SlaveFullName(V.slaves[_ssj])}'s `); + const tmpSpan = makeSpan(block, "father", "lightgreen"); if (slave.relationshipTarget === V.slaves[_ssj].ID) { const friendShipShort = relationshipTerm(slave); - r += ` and ${friendShipShort}`; + tmpSpan.textContent += ` and ${friendShipShort}`; handled = 1; } - r += `.</span> `; + tmpSpan.textContent += '.'; } } else if (slave.daughters > 1) { if (slave.daughters > 10) { - r += `<span class="lightgreen">Has tons of daughters.</span> `; + makeSpan(block, "Has tons of daughters.", "lightgreen"); } else if (slave.daughters > 5) { - r += `<span class="lightgreen">Has many daughters.</span> `; + makeSpan(block, "Has many daughters.", "lightgreen"); } else { - r += `<span class="lightgreen">Has several daughters.</span> `; + makeSpan(block, "Has several daughters.", "lightgreen"); } } if (slave.sisters === 1) { const _ssj = V.slaves.findIndex(s => areSisters(s, slave) > 0); if (_ssj !== -1) { - r += `${SlaveFullName(V.slaves[_ssj])}'s <span class="lightgreen">${getPronouns(slave).sister}`; + addText(block, `${SlaveFullName(V.slaves[_ssj])}'s `); + const tmpSpan = makeSpan(block, getPronouns(slave).sister, "lightgreen"); if (slave.relationshipTarget === V.slaves[_ssj].ID) { const friendShipShort = relationshipTerm(slave); - r += ` and ${friendShipShort}`; + tmpSpan.textContent += ` and ${friendShipShort}`; handled = 1; } - r += `.</span> `; + tmpSpan.textContent += '.'; } } else if (slave.sisters > 1) { if (slave.sisters > 10) { - r += `<span class="lightgreen">One of many sisters.</span> `; + makeSpan(block, "One of many sisters.", "lightgreen"); } else if (slave.sisters > 5) { - r += `<span class="lightgreen">Has many sisters.</span> `; + makeSpan(block, "Has many sisters.", "lightgreen"); } else { - r += `<span class="lightgreen">Has several sisters.</span> `; + makeSpan(block, "Has several sisters.", "lightgreen"); } } if (slave.relationship > 0 && handled !== 1) { const _ssj = V.slaves.findIndex(s => s.ID === slave.relationshipTarget); if (_ssj !== -1) { const friendship = relationshipTerm(slave); - r += `${SlaveFullName(V.slaves[_ssj])}'s `; - r += `<span class="lightgreen">${friendship}.</span> `; + addText(block, `${SlaveFullName(V.slaves[_ssj])}'s `); + makeSpan(block, `${friendship}.`, "lightgreen"); } } else if (slave.relationship === -3 && slave.mother !== -1 && slave.father !== -1) { - r += `<span class="lightgreen">Your wife.</span> `; + makeSpan(block, "Your wife.", "lightgreen"); } else if (slave.relationship === -2) { - r += `<span class="lightgreen">Emotionally bonded to you.</span> `; + makeSpan(block, "Emotionally bonded to you.", "lightgreen"); } else if (slave.relationship === -1) { - r += `<span class="lightgreen">Emotional slut.</span> `; + makeSpan(block, "Emotional slut.", "lightgreen"); + } + + if (block.textContent.length > 0) { + c.appendChild(block); } } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_legacy_family(slave) { + function long_legacy_family(slave, c) { + const block = makeBlock(); if (slave.relation !== 0) { const _ssj = V.slaves.findIndex(s => s.ID === slave.relationTarget); if (_ssj !== -1) { - r += `${SlaveFullName(V.slaves[_ssj])}'s `; + addText(block, `${SlaveFullName(V.slaves[_ssj])}'s `); if (slave.relationshipTarget !== slave.relationTarget) { - r += `<span class="lightgreen">${slave.relation}.</span> `; + makeSpan(block, `${slave.relation}.`, "lightgreen"); } else { - r += `<span class="lightgreen">${slave.relation}</span> `; - } - if (slave.relationship <= 0) { - r += ` `; + makeSpan(block, `${slave.relation}`, "lightgreen"); } } } @@ -4295,672 +3975,659 @@ window.SlaveSummaryUncached = (function() { if (_ssj !== -1) { const friendship = relationshipTerm(slave); if (slave.relationshipTarget !== slave.relationTarget) { - r += `${SlaveFullName(V.slaves[_ssj])}'s `; + addText(block, `${SlaveFullName(V.slaves[_ssj])}'s `); } else { - r += ` and `; + addText(block, `and `); } - r += `<span class="lightgreen">${friendship}.</span> `; + makeSpan(block, `${friendship}.`, "lightgreen"); } } else if (slave.relationship === -3) { - r += `<span class="lightgreen">Your wife.</span> `; + makeSpan(block, "Your wife.", "lightgreen"); } else if (slave.relationship === -2) { - r += `<span class="lightgreen">Emotionally bonded to you.</span> `; + makeSpan(block, "Emotionally bonded to you.", "lightgreen"); } else if (slave.relationship === -1) { - r += `<span class="lightgreen">Emotional slut.</span> `; + makeSpan(block, "Emotional slut.", "lightgreen"); + } + + if (block.textContent.length > 0) { + c.appendChild(block); } } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_clone(slave) { + function long_clone(slave, c) { if (slave.clone !== 0) { - r += ` <span class="skyblue">Clone of ${slave.clone}.</span>`; + makeSpan(c, `Clone of ${slave.clone}.`, "skyblue"); } } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_rival(slave) { + function long_rival(slave, c) { if (slave.rivalry !== 0) { - r += ` `; + const block = makeBlock(c); const _ssj = V.slaves.findIndex(s => s.ID === slave.rivalryTarget); if (_ssj !== -1) { if (slave.rivalry <= 1) { - r += `<span class="lightsalmon">Dislikes</span> ${SlaveFullName(V.slaves[_ssj])}.`; + makeSpan(block, "Dislikes", "lightsalmon"); + block.appendChild(document.createTextNode(` ${SlaveFullName(V.slaves[_ssj])}.`)); } else if (slave.rivalry <= 2) { - r += `${SlaveFullName(V.slaves[_ssj])}'s <span class="lightsalmon">rival.</span>`; + block.appendChild(document.createTextNode(`${SlaveFullName(V.slaves[_ssj])}'s `)); + makeSpan(block, "rival.", "lightsalmon"); } else { - r += `<span class="lightsalmon">Hates</span> ${SlaveFullName(V.slaves[_ssj])}.`; + makeSpan(block, "Hates", "lightsalmon"); + block.appendChild(document.createTextNode(` ${SlaveFullName(V.slaves[_ssj])}.`)); } } - r += " "; } } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_clothes(slave) { - switch (slave.clothes) { - case "attractive lingerie": - r += `Nice lingerie.`; - break; - case "a succubus outfit": - r += `Succubus outfit.`; - break; - case "a string bikini": - r += `String bikini.`; - break; - case "a scalemail bikini": - r += `Scalemail bikini.`; - break; - case "striped panties": - r += `Striped panties.`; - break; - case "a monokini": - r += `Monokini.`; - break; - case "an apron": - r += `Apron.`; - break; - case "a cybersuit": - r += `Cybersuit.`; - break; - case "cutoffs and a t-shirt": - r += `Cutoffs, t-shirt.`; - break; - case "a slutty outfit": - r += `Slutty outfit.`; - break; - case "uncomfortable straps": - r += `Leather straps.`; - break; - case "a fallen nuns habit": - r += `Slutty habit.`; - break; - case "a chattel habit": - r += `Chattel habit.`; - break; - case "a penitent nuns habit": - r += `Cilice.`; - break; - case "slutty jewelry": - r += `Bangles.`; - break; - case "attractive lingerie for a pregnant woman": - r += `Preggo lingerie.`; - break; - case "a maternity dress": - r += `Maternity dress.`; - break; - case "stretch pants and a crop-top": - r += `Stretch pants, crop-top.`; - break; - case "harem gauze": - r += `Harem outfit.`; - break; - case "a slave gown": - r += `Slave gown.`; - break; - case "a halter top dress": - r += `Halter top dress.`; - break; - case "a mini dress": - r += `Mini dress.`; - break; - case "a ball gown": - r += `Ball gown.`; - break; - case "slutty business attire": - r += `Slutty suit.`; - break; - case "nice business attire": - r += `Nice suit.`; - break; - case "a comfortable bodysuit": - r += `Bodysuit.`; - break; - case "a military uniform": - r += `Military uniform.`; - break; - case "a schutzstaffel uniform": - r += `Schutzstaffel uniform.`; - break; - case "a slutty schutzstaffel uniform": - r += `Slutty Schutzstaffel uniform.`; - break; - case "a red army uniform": - r += `Red Army uniform.`; - break; - case "a long qipao": - r += `Long Qipao.`; - break; - case "battlearmor": - r += `Battlearmor.`; - break; - case "a mounty outfit": - r += `Mounty outfit.`; - break; - case "a dirndl": - r += `Dirndl.`; - break; - case "lederhosen": - r += `Lederhosen.`; - break; - case "a biyelgee costume": - r += `Biyelgee costume.`; - break; - case "a leotard": - r += `Leotard.`; - break; - case "a bunny outfit": - r += `Bunny outfit.`; - break; - case "a slutty maid outfit": - r += `Slutty maid.`; - break; - case "a nice maid outfit": - r += `Nice maid.`; - break; - case "a slutty nurse outfit": - r += `Slutty nurse.`; - break; - case "a nice nurse outfit": - r += `Nice nurse.`; - break; - case "a schoolgirl outfit": - r += `Schoolgirl outfit.`; - break; - case "a kimono": - r += `Kimono.`; - break; - case "a hijab and abaya": - r += `Hijab and abaya.`; - break; - case "battledress": - r += `Battledress.`; - break; - case "a latex catsuit": - r += `Nice latex.`; - break; - case "restrictive latex": - r += `Bondage latex.`; - break; - case "conservative clothing": - r += `Conservative clothing.`; - break; - case "chains": - r += `Chains.`; - break; - case "overalls": - r += `Overalls.`; - break; - case "a cheerleader outfit": - r += `Cheerleader.`; - break; - case "clubslut netting": - r += `Netting.`; - break; - case "shibari ropes": - r += `Shibari.`; - break; - case "Western clothing": - r += `Chaps.`; - break; - case "body oil": - r += `Body oil.`; - break; - case "a toga": - r += `Toga.`; - break; - case "a huipil": - r += `Huipil.`; - break; - case "a slutty qipao": - r += `Slutty qipao.`; - break; - case "spats and a tank top": - r += `Spats, tank top.`; - break; - case "a burkini": - r += `Burkini.`; - break; - case "a niqab and abaya": - r += `Niqab and abaya.`; - break; - case "a klan robe": - r += `Klan robe.`; - break; - case "a hijab and blouse": - r += `Hijab and blouse.`; - break; - case "a burqa": - r += `Burqa.`; - break; - case "kitty lingerie": - r += `Kitty lingerie.`; - break; - case "a tube top and thong": - r += `Tube top, thong.`; - break; - case "a button-up shirt and panties": - r += `Button-up shirt, panties.`; - break; - case "a gothic lolita dress": - r += `Gothic lolita dress.`; - break; - case "a hanbok": - r += `Hanbok.`; - break; - case "a bra": - r += `Nice bra.`; - break; - case "a button-up shirt": - r += `Nice button-up shirt.`; - break; - case "a nice pony outfit": - r += `Nice pony outfit.`; - break; - case "a sweater": - r += `Nice sweater.`; - break; - case "a tank-top": - r += `Nice tank-top.`; - break; - case "a thong": - r += `Nice thong.`; - break; - case "a tube top": - r += `Nice tube top.`; - break; - case "a one-piece swimsuit": - r += `Swimsuit.`; - break; - case "a police uniform": - r += `Police uniform.`; - break; - case "a striped bra": - r += `Striped bra.`; - break; - case "a skimpy loincloth": - r += `Skimpy loincloth.`; - break; - case "a slutty klan robe": - r += `Slutty klan robe.`; - break; - case "a slutty pony outfit": - r += `Slutty pony outfit.`; - break; - case "a Santa dress": - r += `Santa dress.`; - break; - case "a sports bra": - r += `Sports bra.`; - break; - case "a sweater and panties": - r += `Sweater, panties.`; - break; - case "a t-shirt": - r += `T-shirt.`; - break; - case "a tank-top and panties": - r += `Tank-top, panties.`; - break; - case "a t-shirt and thong": - r += `Thong, t-shirt.`; - break; - case "an oversized t-shirt and boyshorts": - r += `Over-sized t-shirt, boy shorts.`; - break; - case "an oversized t-shirt": - r += `Nice over-sized t-shirt.`; - break; - case "a t-shirt and jeans": - r += `Blue jeans, t-shirt.`; - break; - case "boyshorts": - r += `Boy shorts.`; - break; - case "cutoffs": - r += `Jean shorts.`; - break; - case "leather pants and pasties": - r += `Leather pants, pasties.`; - break; - case "leather pants": - r += `Nice leather pants.`; - break; - case "panties": - r += `Nice panties.`; - break; - case "sport shorts and a t-shirt": - r += `Nice sport shorts, shirt.`; - break; - case "a t-shirt and panties": - r += `Panties, t-shirt.`; - break; - case "panties and pasties": - r += `Pasties, panties.`; - break; - case "pasties": - r += `Pasties.`; - break; - case "striped underwear": - r += `Striped underwear`; - break; - case "sport shorts and a sports bra": - r += `Shorts, bra.`; - break; - case "jeans": - r += `Tight blue jeans.`; - break; - case "a sweater and cutoffs": - r += `Jean shorts, sweater.`; - break; - case "leather pants and a tube top": - r += `Leather pants, tube top.`; - break; - case "sport shorts": - r += `Shorts.`; - break; - default: - r += `Naked.`; - break; + function long_clothes(slave, c) { + function descStr() { + switch (slave.clothes) { + case "attractive lingerie": + return `Nice lingerie.`; + case "a succubus outfit": + return `Succubus outfit.`; + case "a string bikini": + return `String bikini.`; + case "a scalemail bikini": + return `Scalemail bikini.`; + case "striped panties": + return `Striped panties.`; + case "a monokini": + return `Monokini.`; + case "an apron": + return `Apron.`; + case "a cybersuit": + return `Cybersuit.`; + case "cutoffs and a t-shirt": + return `Cutoffs, t-shirt.`; + case "a slutty outfit": + return `Slutty outfit.`; + case "uncomfortable straps": + return `Leather straps.`; + case "a fallen nuns habit": + return `Slutty habit.`; + case "a chattel habit": + return `Chattel habit.`; + case "a penitent nuns habit": + return `Cilice.`; + case "slutty jewelry": + return `Bangles.`; + case "attractive lingerie for a pregnant woman": + return `Preggo lingerie.`; + case "a maternity dress": + return `Maternity dress.`; + case "stretch pants and a crop-top": + return `Stretch pants, crop-top.`; + case "harem gauze": + return `Harem outfit.`; + case "a slave gown": + return `Slave gown.`; + case "a halter top dress": + return `Halter top dress.`; + case "a mini dress": + return `Mini dress.`; + case "a ball gown": + return `Ball gown.`; + case "slutty business attire": + return `Slutty suit.`; + case "nice business attire": + return `Nice suit.`; + case "a comfortable bodysuit": + return `Bodysuit.`; + case "a military uniform": + return `Military uniform.`; + case "a schutzstaffel uniform": + return `Schutzstaffel uniform.`; + case "a slutty schutzstaffel uniform": + return `Slutty Schutzstaffel uniform.`; + case "a red army uniform": + return `Red Army uniform.`; + case "a long qipao": + return `Long Qipao.`; + case "battlearmor": + return `Battlearmor.`; + case "a mounty outfit": + return `Mounty outfit.`; + case "a dirndl": + return `Dirndl.`; + case "lederhosen": + return `Lederhosen.`; + case "a biyelgee costume": + return `Biyelgee costume.`; + case "a leotard": + return `Leotard.`; + case "a bunny outfit": + return `Bunny outfit.`; + case "a slutty maid outfit": + return `Slutty maid.`; + case "a nice maid outfit": + return `Nice maid.`; + case "a slutty nurse outfit": + return `Slutty nurse.`; + case "a nice nurse outfit": + return `Nice nurse.`; + case "a schoolgirl outfit": + return `Schoolgirl outfit.`; + case "a kimono": + return `Kimono.`; + case "a hijab and abaya": + return `Hijab and abaya.`; + case "battledress": + return `Battledress.`; + case "a latex catsuit": + return `Nice latex.`; + case "restrictive latex": + return `Bondage latex.`; + case "conservative clothing": + return `Conservative clothing.`; + case "chains": + return `Chains.`; + case "overalls": + return `Overalls.`; + case "a cheerleader outfit": + return `Cheerleader.`; + case "clubslut netting": + return `Netting.`; + case "shibari ropes": + return `Shibari.`; + case "Western clothing": + return `Chaps.`; + case "body oil": + return `Body oil.`; + case "a toga": + return `Toga.`; + case "a huipil": + return `Huipil.`; + case "a slutty qipao": + return `Slutty qipao.`; + case "spats and a tank top": + return `Spats, tank top.`; + case "a burkini": + return `Burkini.`; + case "a niqab and abaya": + return `Niqab and abaya.`; + case "a klan robe": + return `Klan robe.`; + case "a hijab and blouse": + return `Hijab and blouse.`; + case "a burqa": + return `Burqa.`; + case "kitty lingerie": + return `Kitty lingerie.`; + case "a tube top and thong": + return `Tube top, thong.`; + case "a button-up shirt and panties": + return `Button-up shirt, panties.`; + case "a gothic lolita dress": + return `Gothic lolita dress.`; + case "a hanbok": + return `Hanbok.`; + case "a bra": + return `Nice bra.`; + case "a button-up shirt": + return `Nice button-up shirt.`; + case "a nice pony outfit": + return `Nice pony outfit.`; + case "a sweater": + return `Nice sweater.`; + case "a tank-top": + return `Nice tank-top.`; + case "a thong": + return `Nice thong.`; + case "a tube top": + return `Nice tube top.`; + case "a one-piece swimsuit": + return `Swimsuit.`; + case "a police uniform": + return `Police uniform.`; + case "a striped bra": + return `Striped bra.`; + case "a skimpy loincloth": + return `Skimpy loincloth.`; + case "a slutty klan robe": + return `Slutty klan robe.`; + case "a slutty pony outfit": + return `Slutty pony outfit.`; + case "a Santa dress": + return `Santa dress.`; + case "a sports bra": + return `Sports bra.`; + case "a sweater and panties": + return `Sweater, panties.`; + case "a t-shirt": + return `T-shirt.`; + case "a tank-top and panties": + return `Tank-top, panties.`; + case "a t-shirt and thong": + return `Thong, t-shirt.`; + case "an oversized t-shirt and boyshorts": + return `Over-sized t-shirt, boy shorts.`; + case "an oversized t-shirt": + return `Nice over-sized t-shirt.`; + case "a t-shirt and jeans": + return `Blue jeans, t-shirt.`; + case "boyshorts": + return `Boy shorts.`; + case "cutoffs": + return `Jean shorts.`; + case "leather pants and pasties": + return `Leather pants, pasties.`; + case "leather pants": + return `Nice leather pants.`; + case "panties": + return `Nice panties.`; + case "sport shorts and a t-shirt": + return `Nice sport shorts, shirt.`; + case "a t-shirt and panties": + return `Panties, t-shirt.`; + case "panties and pasties": + return `Pasties, panties.`; + case "pasties": + return `Pasties.`; + case "striped underwear": + return `Striped underwear`; + case "sport shorts and a sports bra": + return `Shorts, bra.`; + case "jeans": + return `Tight blue jeans.`; + case "a sweater and cutoffs": + return `Jean shorts, sweater.`; + case "leather pants and a tube top": + return `Leather pants, tube top.`; + case "sport shorts": + return `Shorts.`; + default: + return `Naked.`; + } } - r += " "; + makeSpan(c, descStr()); } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_collar(slave) { - switch (slave.collar) { - case "uncomfortable leather": - r += `Leather collar.`; - break; - case "tight steel": - r += `Steel collar.`; - break; - case "preg biometrics": - r += `Pregnancy biometrics collar.`; - break; - case "cruel retirement counter": - r += `Cruel counter collar.`; - break; - case "shock punishment": - r += `Shock collar.`; - break; - case "dildo gag": - r += `Dildo gag.`; - break; - case "massive dildo gag": - r += `Throat-bulging dildo gag.`; - break; - case "neck corset": - r += `Neck corset.`; - break; - case "stylish leather": - r += `Stylish leather collar.`; - break; - case "satin choker": - r += `Satin choker.`; - break; - case "silk ribbon": - r += `Silken ribbon.`; - break; - case "heavy gold": - r += `Gold collar.`; - break; - case "bowtie": - r += `Bowtie collar.`; - break; - case "pretty jewelry": - r += `Pretty collar.`; - break; - case "nice retirement counter": - r += `Nice counter collar.`; - break; - case "bell collar": - r += `Bell collar.`; - break; - case "leather with cowbell": - r += `Cowbell collar.`; - break; - case "ancient Egyptian": - r += `Wesekh.`; - break; - case "ball gag": - r += `Ball gag.`; - break; - case "bit gag": - r += `Bit gag.`; - break; - case "porcelain mask": - r += `Porcelain mask.`; - break; + function long_collar(slave, c) { + function descStr() { + switch (slave.collar) { + case "uncomfortable leather": + return `Leather collar.`; + case "tight steel": + return `Steel collar.`; + case "preg biometrics": + return `Pregnancy biometrics collar.`; + case "cruel retirement counter": + return `Cruel counter collar.`; + case "shock punishment": + return `Shock collar.`; + case "dildo gag": + return `Dildo gag.`; + case "massive dildo gag": + return `Throat-bulging dildo gag.`; + case "neck corset": + return `Neck corset.`; + case "stylish leather": + return `Stylish leather collar.`; + case "satin choker": + return `Satin choker.`; + case "silk ribbon": + return `Silken ribbon.`; + case "heavy gold": + return `Gold collar.`; + case "bowtie": + return `Bowtie collar.`; + case "pretty jewelry": + return `Pretty collar.`; + case "nice retirement counter": + return `Nice counter collar.`; + case "bell collar": + return `Bell collar.`; + case "leather with cowbell": + return `Cowbell collar.`; + case "ancient Egyptian": + return `Wesekh.`; + case "ball gag": + return `Ball gag.`; + case "bit gag": + return `Bit gag.`; + case "porcelain mask": + return `Porcelain mask.`; + default: + return null; + } + } + const s = descStr(); + if (s) { + makeSpan(c, s); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_belly(slave) { - switch (slave.bellyAccessory) { - case "shapewear": - r += `Shapewear.`; - break; - case "a small empathy belly": - r += `Small fake belly.`; - break; - case "a medium empathy belly": - r += `Medium fake belly.`; - break; - case "a large empathy belly": - r += `Large fake belly.`; - break; - case "a huge empathy belly": - r += `Huge fake belly.`; - break; - case "a corset": - r += `Corset.`; - break; - case "an extreme corset": - r += `Extreme corsetage.`; - break; + function long_belly(slave, c) { + function descStr() { + switch (slave.bellyAccessory) { + case "shapewear": + return `Shapewear.`; + case "a small empathy belly": + return `Small fake belly.`; + case "a medium empathy belly": + return `Medium fake belly.`; + case "a large empathy belly": + return `Large fake belly.`; + case "a huge empathy belly": + return `Huge fake belly.`; + case "a corset": + return `Corset.`; + case "an extreme corset": + return `Extreme corsetage.`; + default: + return null; + } + } + const s = descStr(); + if (s) { + makeSpan(c, s); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_arms(slave) { - if (slave.armAccessory === "hand gloves") { - r += `Hand gloves.`; - } else if (slave.armAccessory === "elbow gloves") { - r += `Elbow gloves.`; + function long_arms(slave, c) { + if (["hand gloves", "elbow gloves"].includes(slave.armAccessory)) { + makeSpan(c, slave.armAccessory, undefined, true); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_legs(slave) { + function long_legs(slave, c) { if (slave.legAccessory === "short stockings") { - r += `Short stockings.`; + makeSpan(c, "Short stockings."); } else if (slave.legAccessory === "long stockings") { - r += `Long stockings.`; + makeSpan(c, "Long stockings."); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_shoes(slave) { - if (slave.shoes === "heels") { - r += `Heels.`; - } else if (slave.shoes === "pumps") { - r += `Pumps.`; - } else if (slave.shoes === "extreme heels") { - r += `Extreme heels.`; - } else if (slave.shoes === "boots") { - r += `Boots.`; + function long_shoes(slave, c) { + if (["heels", "pumps", "extreme heels", "boots", "flats"].includes(slave.shoes)) { + makeSpan(c, slave.shoes, undefined, true); } else if (slave.heels === 1) { - r += `<span class="yellow">Crawling.</span>`; - } else if (slave.shoes === "flats") { - r += `Flats.`; + makeSpan(c, "Crawling.", "yellow"); } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_chastity(slave) { + function long_chastity(slave, c) { if (slave.chastityAnus === 1 && slave.chastityPenis === 1 && slave.chastityVagina === 1) { - r += `Full chastity.`; + makeSpan(c, "Full chastity."); } else if (slave.chastityPenis === 1 && slave.chastityVagina === 1) { - r += `Genital chastity.`; + makeSpan(c, "Genital chastity."); } else if ((slave.chastityAnus === 1 && slave.chastityVagina === 1) || (slave.chastityAnus === 1 && slave.chastityPenis === 1)) { - r += `Combined chastity.`; + makeSpan(c, "Combined chastity."); } else if (slave.chastityVagina === 1) { - r += `Vaginal chastity.`; + makeSpan(c, "Vaginal chastity."); } else if (slave.chastityPenis === 1) { - r += `Chastity cage.`; + makeSpan(c, "Chastity cage."); } else if (slave.chastityAnus === 1) { - r += `Anal chastity.`; + makeSpan(c, "Anal chastity."); } } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_vaginal_acc(slave) { + function long_vaginal_acc(slave, c) { if (slave.vaginalAttachment !== "vibrator") { switch (slave.vaginalAccessory) { case "bullet vibrator": - r += `Attached bullet vibrator.`; + makeSpan(c, "Attached bullet vibrator."); break; case "smart bullet vibrator": - r += `Attached smart bullet vibrator.`; + makeSpan(c, "Attached smart bullet vibrator."); break; case "dildo": - r += `Vaginal dildo.`; + makeSpan(c, "Vaginal dildo."); break; case "large dildo": - r += `Large vaginal dildo.`; + makeSpan(c, "Large vaginal dildo."); break; case "huge dildo": - r += `Huge vaginal dildo.`; + makeSpan(c, "Huge vaginal dildo."); break; case "long dildo": - r += `Long vaginal dildo.`; + makeSpan(c, "Long vaginal dildo."); break; case "long, large dildo": - r += `Long and large vaginal dildo.`; + makeSpan(c, "Long and large vaginal dildo."); break; case "long, huge dildo": - r += `Long and wide vaginal dildo.`; + makeSpan(c, "Long and wide vaginal dildo."); break; } } - r += " "; if (slave.vaginalAttachment !== "none") { switch (slave.vaginalAttachment) { case "vibrator": - r += `Vibrating dildo.`; + makeSpan(c, "Vibrating dildo."); break; } - r += " "; } } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_dick_acc(slave) { + function long_dick_acc(slave, c) { switch (slave.dickAccessory) { case "sock": - r += `Cock sock.`; + makeSpan(c, "Cock sock."); break; case "bullet vibrator": - r += `Frenulum bullet vibrator.`; + makeSpan(c, "Frenulum bullet vibrator."); break; case "smart bullet vibrator": - r += `Smart frenulum bullet vibrator.`; + makeSpan(c, "Smart frenulum bullet vibrator."); break; } - r += " "; } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function long_buttplug(slave) { + function long_buttplug(slave, c) { switch (slave.buttplug) { case "plug": - r += `Buttplug.`; + makeSpan(c, "Buttplug."); break; case "large plug": - r += `Large buttplug.`; + makeSpan(c, "Large buttplug."); break; case "huge plug": - r += `Huge buttplug.`; + makeSpan(c, "Huge buttplug."); break; case "long plug": - r += `Long buttplug.`; + makeSpan(c, "Long buttplug."); break; case "long, large plug": - r += `Large, long buttplug.`; + makeSpan(c, "Large, long buttplug."); break; case "long, huge plug": - r += `Enormous buttplug.`; + makeSpan(c, "Enormous buttplug."); break; } - r += " "; switch (slave.buttplugAttachment) { case "tail": - r += `Attached tail. `; + makeSpan(c, "Attached tail."); break; case "cat tail": - r += `Attached cat tail. `; + makeSpan(c, "Attached cat tail."); break; case "fox tail": - r += `Attached fox tail. `; + makeSpan(c, "Attached fox tail."); break; case "cow tail": - r += `Attached cow tail. `; + makeSpan(c, "Attached cow tail."); break; } } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function rules_assistant(slave) { + function rules_assistant(slave, c) { if (slave.useRulesAssistant === 0) { - r += `<span class="lightgreen">RA-Exempt</span> `; + makeSpan(c, "RA-Exempt", "lightgreen"); } else if (V.abbreviateRulesets === 2 && (slave.currentRules !== undefined) && (slave.currentRules.length > 0)) { - r += `Rules: ${V.defaultRules.filter(x => ruleApplied(slave, x)).map(x => x.name).join(", ")}`; + c.appendChild(document.createTextNode(`Rules: ${V.defaultRules.filter(x => ruleApplied(slave, x)).map(x => x.name).join(", ")}`)); } } /** * @param {App.Entity.SlaveState} slave + * @param {Node} c + * @returns {void} */ - function origins(slave) { - r += `<br>`; - if (V.seeImages !== 1 || V.seeSummaryImages !== 1 || V.imageChoice === 1) { - r += ` `; - } + function origins(slave, c) { + const para = makeParagraph(c); + para.classList.add("gray"); const pronouns = getPronouns(slave); - r += `<span class="gray">${slave.origin.replace(/\$([A-Z]?[a-z]+)/g, (match, cap1) => pronouns[cap1] || match)}</span>`; + para.textContent = `${slave.origin.replace(/\$([A-Z]?[a-z]+)/g, (match, cap1) => pronouns[cap1] || match)}`; + } + + /** + * @param {HTMLElement} element + * @param {string|string[]} [classNames] + */ + function _addClassNames(element, classNames) { + if (classNames != undefined) { /* eslint-disable-line eqeqeq */ + if (Array.isArray(classNames)) { + element.classList.add(...classNames); + } else { + element.classList.add(classNames); + } + } + } + + /** + * @param {Node} container + * @param {string} text + * @param {string|string[]} [classNames] + * @param {boolean} [stdDecor=false] + * @param {number} [value] + */ + function makeSpan(container, text, classNames, stdDecor = false, value) { + let r = document.createElement("span"); + r.classList.add("ssi"); + _addClassNames(r, classNames); + if (value != undefined && V.summaryStats) { /* eslint-disable-line eqeqeq */ + text += `[${value}]`; + } + r.textContent = stdDecor ? `${capFirstChar(text)}.` : text; + if (container) { + container.appendChild(r); + } + return r; + } + + /** + * @param {Node} container + * @param {string} text + * @returns {Text} + */ + function addText(container, text) { + const r = document.createTextNode(text); + if (container) { + container.appendChild(r); + } + return r; + } + + /** + * @param {Node} [container] + * @param {string|string[]} [classNames] + */ + function makeBlock(container, classNames) { + let r = document.createElement("span"); + r.classList.add("ssb"); + _addClassNames(r, classNames); + if (container) { + container.appendChild(r); + } + return r; + } + + /** + * @param {Node} container + * @param {string|string[]} [classNames] + * @returns {HTMLParagraphElement} + */ + function makeParagraph(container, classNames) { + let r = document.createElement("p"); + r.classList.add("si"); + _addClassNames(r, classNames); + if (container) { + container.appendChild(r); + } + return r; + } + + /** + * @param {Node} container + * @param {string} name + * @param {string} content + */ + function tag(container, name, content) { + let r = document.createElement(name); + r.textContent = content; + if (container) { + container.appendChild(r); + } + return r; } return SlaveSummaryUncached; + })(); diff --git a/src/js/utilsDOM.js b/src/js/utilsDOM.js new file mode 100644 index 0000000000000000000000000000000000000000..094cd5751c84e2db12a32d47243c62faddeb3d1e --- /dev/null +++ b/src/js/utilsDOM.js @@ -0,0 +1,170 @@ +/** + * @callback passageLinkHandler + * @returns {void} + */ +/** + * Creates a HTML element with custom SugarCube attributes which works as a passage link + * + * The result works in the same way as the wiki markup in the SugarCube + * @see https://www.motoslave.net/sugarcube/2/docs/#markup-html-attribute + * @param {string} linkText link text + * @param {string} passage the passage name to link to + * @param {passageLinkHandler} [handler] setter text (optional) + * @param {string} [tooltip=''] tooltip text (optional) + * @param {string} [elementType='a'] element type (optional) default is 'a'. + * Could be any of 'a', 'audio', img', 'source', 'video' + * @returns {HTMLElement} element text + * + * @example + * // equal to [[Go to town|Town]] + * App.UI.passageLink("Go to town", "Town") + */ +App.UI.DOM.passageLink = function(linkText, passage, handler, tooltip = '', elementType = 'a') { + let res = document.createElement(elementType); + res.setAttribute("data-passage", passage); + res.onclick = (ev) => { + ev.preventDefault(); + if (handler) { + handler(); + } + Engine.play(passage); + }; + + if (tooltip) { + res.title = tooltip; + } + res.textContent = linkText; + return res; +}; + +/** + * Returns link element for an assignment + * @param {App.Entity.SlaveState} slave + * @param {string} assignment + * @param {string} [passage] passage to go to + * @param {assignmentCallback} [callback] + * @param {string} [linkText] + * @returns {HTMLAnchorElement} + */ +App.UI.DOM.assignmentLink = function(slave, assignment, passage, callback, linkText) { + let res = document.createElement("a"); + res.textContent = linkText; + res.onclick = (e) => { + e.preventDefault(); + assignJob(slave, assignment); + if (callback) { + callback(this.desc.assignment); + } + if (passage !== '') { + SugarCube.Engine.play(passage); + } + }; + return res; +}; + +App.UI.DOM.link = function() { + return makeLink; + + /** + * Creates a markup for a SugarCube link which executes given function with given arguments + * + * @param {string} linkText link text + * @param {*} handler callable object + * @param {*} args arguments + * @param {string} [passage] the passage name to link to + * @returns {HTMLAnchorElement} link in SC markup + */ + function makeLink(linkText, handler, args = [], passage = '', tooltip = '') { + const hArgs = Array.isArray(args) ? args : [args]; + let link = document.createElement("a"); + link.textContent = linkText; + link.title = tooltip; + link.onclick = () => { + handler(...hArgs); + if (passage !== '') { + SugarCube.Engine.play(passage); + } + }; + return link; + } +}(); + +/** + * Creates a span for an link with tooltip containing the reasons why it is disabled + * @param {string} link + * @param {string[]} reasons + * @returns {HTMLSpanElement} + */ +App.UI.DOM.disabledLink = function(link, reasons) { + /** @type {HTMLElement} */ + let tooltip; + if (reasons.length === 1) { + tooltip = document.createElement("span"); + tooltip.textContent = reasons[0]; + } else { + tooltip = document.createElement("div"); + let ul = document.createElement("ul"); + for (const li of reasons.map(r => { + const li = document.createElement("li"); + li.textContent = r; + return li; + })) { + ul.appendChild(li); + } + } + tooltip.className = "tooltip"; + let res = document.createElement("span"); + res.textContent = link; + res.className = "textWithTooltip"; + res.appendChild(tooltip); + return res; +}; + +/** +* @param {string} text +* @param {string|string[]} [classNames] +*/ +App.UI.DOM.makeSpan = function makeSpan(text, classNames) { + let r = document.createElement("span"); + if (classNames !== undefined) { + if (Array.isArray(classNames)) { + r.classList.add(...classNames); + } else { + r.classList.add(classNames); + } + } + r.innerHTML = text; + return r; +}; + +/** + * @param {string} passage + * @return {Element} + */ +App.Utils.passageElement = function(passage) { + return document.querySelector(`tw-passagedata[name="${passage}"]`); +}; + +/** + * @param {Node[]} nodes + * @returns {DocumentFragment} + */ +App.UI.DOM.combineNodes = function(...nodes) { + let res = document.createDocumentFragment(); + for (const n of nodes) { + res.appendChild(n); + } + return res; +}; + +/** + * @param {string} text + * @returns {HTMLElement} + */ +App.Utils.htmlToElement = function(text) { + const template = document.createElement("template"); + text = text.trim(); // Never return a text node of whitespace as the result + template.innerHTML = text; + // @ts-ignore + return template.content.firstChild; +}; diff --git a/src/npc/agent/agentSelect.tw b/src/npc/agent/agentSelect.tw index 5c6ff3eaf43e6ac97bcd2aa2b1b6938144c2ba39..3fb70d8818209ddf2e0d1874e6bc212c64d7f8f2 100644 --- a/src/npc/agent/agentSelect.tw +++ b/src/npc/agent/agentSelect.tw @@ -5,6 +5,7 @@ <<= App.UI.SlaveList.slaveSelectionList( s => (s.fuckdoll === 0 && s.devotion > 20 && s.intelligence + s.intelligenceImplant > 15 && s.intelligenceImplant >= 15 && canWalk(s) && canSee(s) && canHear(s) && canTalk(s) && s.broodmother < 2 && (s.breedingMark !== 1 || State.variables.propOutcome === 0 || State.variables.eugenicsFullControl === 1 || State.variables.arcologies[0].FSRestart === "unset")), - (slave, index) => App.UI.passageLink(SlaveFullName(slave), 'Agent Workaround', `$i = ${index}`), + (slave, index) => App.UI.DOM.passageLink(SlaveFullName(slave), 'Agent Workaround', + () => { variables().i = index; }), s => App.Entity.facilities.arcologyAgent.manager.slaveHasExperience(s) )>> diff --git a/src/uncategorized/coursingAssociation.tw b/src/uncategorized/coursingAssociation.tw index 083551e337a2d136ebffc1641d936ebc37ad38f4..a0ca2d88441f1429ac3915bf2ab402598447cf2d 100644 --- a/src/uncategorized/coursingAssociation.tw +++ b/src/uncategorized/coursingAssociation.tw @@ -16,7 +16,7 @@ The chasing slaves are known as lurchers, the term once used for the sighthounds <<if $Lurcher != 0>> <br><br>''Fire your Lurcher:'' - <<= App.UI.SlaveList.render([App.Utils.slaveIndexForId($Lurcher.ID)], [], + <<= App.UI.SlaveList.render.listMarkup([App.Utils.slaveIndexForId($Lurcher.ID)], [], (slave, index) => App.UI.passageLink(SlaveFullName(slave), 'Retrieve', `$i = ${App.Utils.slaveIndexForId($Lurcher.ID)}`))>> <</if>> @@ -24,5 +24,5 @@ The chasing slaves are known as lurchers, the term once used for the sighthounds <br><br> <<= App.UI.SlaveList.slaveSelectionList( s => $Lurcher.ID !== s.ID && canWalk(s) && (s.assignmentVisible === 1 && s.fuckdoll === 0), - (slave, index) => App.UI.passageLink(SlaveFullName(slave), 'Assign', `$i = ${index}`) + (slave, index) => App.UI.DOM.passageLink(SlaveFullName(slave), 'Assign', () => { variables().i = index; }) )>> diff --git a/src/uncategorized/matchmaking.tw b/src/uncategorized/matchmaking.tw index b5429aaca992e70e2438c094e4c519b5eea503d5..3b15c83ef7ae22974a6289cc73e2c9506bc11414 100644 --- a/src/uncategorized/matchmaking.tw +++ b/src/uncategorized/matchmaking.tw @@ -385,7 +385,7 @@ Despite $his devotion and trust, $he is still a slave, and probably knows that $ s => s.devotion >= 100 && s.relationship === $activeSlave.relationship && s.ID !== $activeSlave.ID, App.UI.SlaveList.SlaveInteract.stdInteract, null, - (s, i) => App.UI.passageLink('Match them', 'Matchmaking', `$subSlave = $slaves[${i}]`) + (s, i) => App.UI.DOM.passageLink('Match them', 'Matchmaking', () => { variables().subSlave = App.Utils.slaveByIndex(i); }) )>> </span> diff --git a/src/uncategorized/options.tw b/src/uncategorized/options.tw index cf52a4c26aceb8d487fee25284ecc69a41a1b38b..c33e7848415a95b964fd2dc88a0f88e8fbcf15e7 100644 --- a/src/uncategorized/options.tw +++ b/src/uncategorized/options.tw @@ -296,7 +296,7 @@ This save was created using FC version $ver build $releaseID. <</options>> <<if $seeImages > 0>> - <div style="position:relative;width:200px;height:200px;margin:0 auto;"> + <div class="imageRef" style="width:200px;height:200px;margin:0 auto;"> <<= SlaveArt(BaseSlave(), 0, 0)>> </div> diff --git a/src/uncategorized/personalAttentionSelect.tw b/src/uncategorized/personalAttentionSelect.tw index 818ea3557201c450e3281425b83651fde484de1a..bea85578a9ceff32296d6cffc9fa67dba70948ee 100644 --- a/src/uncategorized/personalAttentionSelect.tw +++ b/src/uncategorized/personalAttentionSelect.tw @@ -350,5 +350,5 @@ <br><br>__Select a slave to train:__ <<if $PC.slaving >= 100>>//Your @@.springgreen;slaving experience@@ allows you to divide your attention between more than one slave each week, with slightly reduced efficiency//<</if>> <<= App.UI.SlaveList.slaveSelectionList( s => s.assignmentVisible === 1 && s.fuckdoll === 0, - s => `<<link "${SlaveFullName(s)}">><<run App.UI.selectSlaveForPersonalAttention(${s.ID})>><</link>>` + s => App.UI.DOM.link(SlaveFullName(s), (id) => {App.UI.selectSlaveForPersonalAttention(id); }, s.ID) )>> diff --git a/src/uncategorized/rulesSlaveSelect.tw b/src/uncategorized/rulesSlaveSelect.tw index abda187c938d3914eb83c4c2999e9c17fa213fdb..7b72d51ff14f3bdd25acf649858b16f62a669d88 100644 --- a/src/uncategorized/rulesSlaveSelect.tw +++ b/src/uncategorized/rulesSlaveSelect.tw @@ -12,18 +12,33 @@ Select slaves to exclude from Rule $r: <<print App.UI.SlaveList.slaveSelectionList( s => !ruleSlaveSelected(s, $currentRule), - (s, i) => `<u><strong>${App.UI.passageLink(SlaveFullName(s), 'Rules Slave Select Workaround', `$activeSlave = $slaves[${i}]`)}</strong></u>` + (s, i) => { + let l = App.UI.DOM.passageLink(SlaveFullName(s), 'Rules Slave Select Workaround', + () => { App.Utils.setActiveSlaveByIndex(i); }); + l.classList.add("emphasizedSlave"); + return l; + } )>> <<else>> Rule $r currently limited to specific slaves: [[Clear list|Rules Slave Select][$currentRule.selectedSlaves = []]] <<print App.UI.SlaveList.slaveSelectionList( s => ruleSlaveSelected(s, $currentRule), - (s, i) => `<u><strong>${App.UI.passageLink(SlaveFullName(s), 'Rules Slave Deselect Workaround', `$activeSlave = $slaves[${i}]`)}</strong></u>` + (s, i) => { + let l = App.UI.DOM.passageLink(SlaveFullName(s), 'Rules Slave Deselect Workaround', + () => { App.Utils.setActiveSlaveByIndex(i); }); + l.classList.add("emphasizedSlave"); + return l; + } )>> <br><br> Choose more specific slaves: <<print App.UI.SlaveList.slaveSelectionList( s => !ruleSlaveSelected(s, $currentRule), - (s, i) => `<u><strong>${App.UI.passageLink(SlaveFullName(s), 'Rules Slave Select Workaround', `$activeSlave = $slaves[${i}]`)}</strong></u>` + (s, i) => { + let l = App.UI.DOM.passageLink(SlaveFullName(s), 'Rules Slave Select Workaround', + () => { App.Utils.setActiveSlaveByIndex(i); }); + l.classList.add("emphasizedSlave"); + return l; + } )>> <</if>> diff --git a/src/uncategorized/subordinateTargeting.tw b/src/uncategorized/subordinateTargeting.tw index a742da8af47876f40994340b5ebf7799eda33e34..7d90320cc0b9a8854b8fcfcb78d485733080c893 100644 --- a/src/uncategorized/subordinateTargeting.tw +++ b/src/uncategorized/subordinateTargeting.tw @@ -21,7 +21,7 @@ <<= App.UI.SlaveList.slaveSelectionList( s => s.devotion >= -20 && s.fuckdoll === 0 && State.variables.activeSlave.ID !== s.ID && (State.variables.activeSlave.amp !== 1 || s.amp !== 1), - (s, i) => App.UI.passageLink(SlaveFullName(s), 'Subordinate Targeting', `$activeSlave.subTarget = ${s.ID}`), + (s, i) => App.UI.DOM.passageLink(SlaveFullName(s), 'Subordinate Targeting', () => { App.activeSlave.subTarget = s.ID; }), )>> <br><br>[[None|Subordinate Targeting][$activeSlave.subTarget = 0]]