diff options
author | QCyph <dev@lived.nl> | 2011-08-27 10:50:29 +0200 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2011-08-27 11:01:10 +0200 |
commit | e26056de79c72a113fa1c5cc725e053e0efe3a97 (patch) | |
tree | 015770471e514ef07a73e3d7e813eae04e117975 | |
parent | 96c8f09ca054ea21f59bd62b3fdc9de90ebf1348 (diff) |
Added filters to character browse page and trait page
-rw-r--r-- | data/global.pl | 5 | ||||
-rw-r--r-- | data/lang.txt | 179 | ||||
-rw-r--r-- | data/script.js | 90 | ||||
-rw-r--r-- | lib/VNDB/DB/Chars.pm | 19 | ||||
-rw-r--r-- | lib/VNDB/Handler/Chars.pm | 20 | ||||
-rw-r--r-- | lib/VNDB/Handler/Traits.pm | 15 | ||||
-rw-r--r-- | lib/VNDB/Util/Misc.pm | 5 | ||||
-rwxr-xr-x | util/jsgen.pl | 7 |
8 files changed, 302 insertions, 38 deletions
diff --git a/data/global.pl b/data/global.pl index 31d45631..844d69d1 100644 --- a/data/global.pl +++ b/data/global.pl @@ -102,6 +102,11 @@ our %S = (%S, vnlist_status => [ 0..4 ], blood_types => [qw| unknown a b ab o |], genders => [qw| unknown m f b |], + bust_ranges => [ 50, 60, 65, 70, 75, 80, 85, 90, 100, 110, 120 ], + waist_ranges => [ 40, 50, 55, 60, 65, 70, 75, 80 ], + hip_ranges => [ 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100 ], + height_ranges => [ 10, 50, 100, 120, 140, 150, 160, 170, 180, 190, 200, 220, 240, 280 ], + weight_ranges => [ 20, 50, 60, 70, 80, 90, 100, 150, 200, 250, 350 ], char_roles => [qw| main primary side appears |], atom_feeds => { # num_entries, title, id announcements => [ 10, 'VNDB Site Announcements', '/t/an' ], diff --git a/data/lang.txt b/data/lang.txt index 9639cc11..90463878 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -1533,6 +1533,13 @@ cs : -dne- hu : -nap- nl : -dag- +:_js_remove +en : remove +ru : убрать +cs : odstranit +hu : eltávolítás +nl : verwijder + :_js_ds_noresults en : No results... ru : Совпадений не найдено... @@ -1575,6 +1582,27 @@ cs : Zde se nedají použít meta-tagy! hu : Itt nem használhatsz meta címkéket! nl : Meta tags kunnen hier niet gebruikt worden! +:_js_ds_trait_meta +en : meta +ru*: +cs*: +hu*: +nl : + +:_js_ds_trait_mod +en : awaiting moderation +ru*: +cs*: +hu*: +nl : ongemodereerd + +:_js_ds_trait_nometa +en : Can't use meta traits here! +ru*: +cs*: +hu*: +nl : Meta kenmerken kunnen hier niet gebruikt worden! + # Filter selector @@ -5571,8 +5599,152 @@ cs : Žádné postavy odpovídající vašim požadavkům. hu : A kritériumaid alapján nem található szereplő. nl : Geen karakters gevonden die aan je kriteria voldoen. +:_charb_fil_title +en : Character filters +ru*: +cs*: +hu*: +nl : Karakterfilters + +:_charb_general +en : General +ru*: +cs*: +hu*: +nl : Algemeen + +:_charb_gender +en : Gender +ru*: +cs*: +hu*: +nl : Geslacht +:_charb_bust_min +en : Bust min +ru*: +cs*: +hu*: +nl : Borst min +:_charb_bust_max +en : Bust max +ru*: +cs*: +hu*: +nl : Borst max + +:_charb_waist_min +en : Waist min +ru*: +cs*: +hu*: +nl : Taille min + +:_charb_waist_max +en : Waist max +ru*: +cs*: +hu*: +nl : Taille max + +:_charb_hip_min +en : Hips min +ru*: +cs*: +hu*: +nl : Heupen min + +:_charb_hip_max +en : Hips max +ru*: +cs*: +hu*: +nl : Heupen max + +:_charb_height_min +en : Height min +ru*: +cs*: +hu*: +nl : Lengte min + +:_charb_height_max +en : Height max +ru*: +cs*: +hu*: +nl : Lengte max + +:_charb_weight_min +en : Weight min +ru*: +cs*: +hu*: +nl : Gewicht min + +:_charb_weight_max +en : Weight max +ru*: +cs*: +hu*: +nl : Gewicht max + +:_charb_bloodt +en : Blood type +ru*: +cs*: +hu*: +nl : Bloedgroep + +:_charb_traits +en : Traits +ru*: +cs*: +hu*: +nl : Kenmerken + +:_charb_traitinc +en : Traits to include +ru*: +cs*: +hu*: +nl : Kenmerken meenemen + +:_charb_traitexc +en : Traits to exclude +ru*: +cs*: +hu*: +nl : Kenmerken uitsluiten + +:_charb_traitnothere +en : Additional trait filters are not available on this page. Use the character browser instead (available from the main menu -> characters). +ru*: +cs*: +hu*: +nl : Extra kenmerkfilters zijn niet aanwezig op deze pagina. Gebruik de karakterbrowser voor deze functionaliteit (beschikbaar via het hoofdmenu -> karakters). + +:_charb_spoil0 +en : Hide spoilers +ru*: +cs*: +hu*: +nl : Verberg spoilers + +:_charb_spoil1 +en : Show minor spoilers +ru*: +cs*: +hu*: +nl : Toon geringe spoilers + +:_charb_spoil2 +en : Show major spoilers +ru*: +cs*: +hu*: +nl : Toon alle spoilers @@ -7131,13 +7303,6 @@ cs : Tyto filtry jsou na stránkách tagů ignorovány (když jsou nastaveny jak hu : Ezzek a szűrők figyelmen kívűl maradnak a címke oldalakon (ha alapértelmezetnek vannak beállítva). nl : Deze filters worden genegeerd op tagpaginas (als ze gebruikt worden als standaardfilters). -:_vnbrowse_tagrem -en : remove -ru : убрать -cs : odstranit -hu : eltávolítás -nl : verwijder - :_vnbrowse_taginc en : Tags to include ru : Включить теги diff --git a/data/script.js b/data/script.js index e85bce3d..824ca12a 100644 --- a/data/script.js +++ b/data/script.js @@ -2124,7 +2124,9 @@ if(byId('jt_box_chare_vns')) var fil_cats; // [ <object with field->tr mapping>, <category-link1>, .. ] var fil_escape = "_ !\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~".split(''); function filLoad() { - var l = byId('filselect').href.match(/#r$/) ? filReleases() : filVN(); + var l = byId('filselect').href.match(/#r$/) ? filReleases() + : byId('filselect').href.match(/#c$/) ? filChars() + : filVN(); fil_cats = [ new Object ]; var p = tag('p', {'class':'browseopts'}); @@ -2179,7 +2181,8 @@ function filLoad() { f.submit(); }}), tag('input', {type:'button', 'class':'submit', value: mt('_js_fil_reset'), onclick:function () { byId('fil').value = ''; filDeSerialize()} }), - PREF_CODE != '' ? tag('input', {type:'button', 'class':'submit', value: mt('_js_fil_save'), onclick:filSaveDefault }) : null, + typeof PREFS != 'undefined' && ('filter_vn' in PREFS | 'filter_release' in PREFS) && PREF_CODE != '' ? + tag('input', {type:'button', 'class':'submit', value: mt('_js_fil_save'), onclick:filSaveDefault }) : null, tag('p', {id:'fil_savenote', 'class':'hidden'}, '') )); filSelectCat(1); @@ -2265,7 +2268,7 @@ function filSerialize() { if(r.length > 0 && r[0] != '') values[fil_cats[0][f].fil_code] = r.join('~'); } - if(!values['tag_inc']) + if(!values['tag_inc'] && !values['trait_inc']) delete values['tagspoil']; var l = []; for(var f in values) @@ -2379,14 +2382,16 @@ function filFOptions(c, n, opts, setfunc) { ]; } -function filFTagInput(name, label) { +function filFTagInput(name, label, type) { + var src = type=='tag' ? '/xml/tags.xml' : '/xml/traits.xml'; + var visible = false; var remove = function() { ; }; var addtag = function(ul, id, name) { ul.appendChild(tag('li', { fil_id: id }, - tag('a', {href:'/g'+id}, name||'g'+id), + type=='tag' ? tag('a', {href:'/g'+id}, name||'g'+id) : tag('a', {href:'/i'+id}, name||'i'+id), ' (', tag('a', {href:'#', onclick:function () { // a -> li -> ul -> div @@ -2395,7 +2400,7 @@ function filFTagInput(name, label) { filSelectField(ul.parentNode); return false } - }, mt('_vnbrowse_tagrem')), ')' + }, mt('_js_remove')), ')' )); } var fetch = function(c) { @@ -2421,7 +2426,7 @@ function filFTagInput(name, label) { txt.value = mt('_js_loading'); txt.disabled = true; if(visible) - ajax('/xml/tags.xml?'+q.join(';'), function (hr) { + ajax(src+'?'+q.join(';'), function (hr) { var l = []; var items = hr.responseXML.getElementsByTagName('item'); setText(ul, ''); @@ -2434,16 +2439,16 @@ function filFTagInput(name, label) { }; var input = tag('input', {type:'text', 'class':'text', style:'width:300px', onfocus:filSelectField}); var list = tag('ul', null); - dsInit(input, '/xml/tags.xml?q=', + dsInit(input, src+'?q=', function(item, tr) { - tr.appendChild(tag('td', shorten(item.firstChild.nodeValue, 40), - item.getAttribute('meta') == 'yes' ? tag('b', {'class': 'grayedout'}, ' '+mt('_js_ds_tag_meta')) : null, - item.getAttribute('state') == 0 ? tag('b', {'class': 'grayedout'}, ' '+mt('_js_ds_tag_mod')) : null + tr.appendChild(tag('td', shorten(item.firstChild.nodeValue, 40), // l10n /_js_ds_(tag|trait)_(meta|mod)/ + item.getAttribute('meta') == 'yes' ? tag('b', {'class': 'grayedout'}, ' '+mt('_js_ds_'+type+'_meta')) : null, + item.getAttribute('state') == 0 ? tag('b', {'class': 'grayedout'}, ' '+mt('_js_ds_'+type+'_mod')) : null )); }, function(item, obj) { - if(item.getAttribute('meta') == 'yes') - alert(mt('_js_ds_tag_nometa')); + if(item.getAttribute('meta') == 'yes') // l10n /_js_ds_(tag|trait)_nometa/ + alert(mt('_js_ds_'+type+'_nometa')); else { addtag(byName(obj.parentNode, 'ul')[0], item.getAttribute('id'), item.firstChild.nodeValue); filSelectField(obj); @@ -2466,6 +2471,61 @@ function filFTagInput(name, label) { ]; } +function filChars() { + var gend = genders; + for(var i=0; i<gend.length; i++) // l10n /_gender_.+/ + gend[i] = [ gend[i], mt('_gender_'+gend[i]) ]; + var bust = bust_ranges; + for(var i=0; i<bust.length; i++) + bust[i] = [ bust[i], bust[i]+' cm' ]; + var waist = waist_ranges; + for(var i=0; i<waist.length; i++) + waist[i] = [ waist[i], waist[i]+' cm' ]; + var hip = hip_ranges; + for(var i=0; i<hip.length; i++) + hip[i] = [ hip[i], hip[i]+' cm' ]; + var height = height_ranges; + for(var i=0; i<height.length; i++) + height[i] = [ height[i], height[i]+' cm' ]; + var weight = weight_ranges; + for(var i=0; i<weight.length; i++) + weight[i] = [ weight[i], weight[i]+' kg' ]; + var bloodt = blood_types; + for(var i=0; i<bloodt.length; i++) // l10n /_bloodt_.+/ + bloodt[i] = [ bloodt[i], mt('_bloodt_'+bloodt[i]) ]; + + var ontraitpage = location.pathname.indexOf('/c/') < 0; + + return [ + mt('_charb_fil_title'), + [ mt('_charb_general'), + filFSelect('gender', mt('_charb_gender'), 4, gend), + filFSelect('bloodt', mt('_charb_bloodt'), 5, bloodt), + '', + filFSelect('bust_min', mt('_charb_bust_min'), 1, bust), + filFSelect('bust_max', mt('_charb_bust_max'), 1, bust), + filFSelect('waist_min', mt('_charb_waist_min'), 1, waist), + filFSelect('waist_max', mt('_charb_waist_max'), 1, waist), + filFSelect('hip_min', mt('_charb_hip_min'), 1, hip), + filFSelect('hip_max', mt('_charb_hip_max'), 1, hip), + '', + filFSelect('height_min', mt('_charb_height_min'), 1, height), + filFSelect('height_max', mt('_charb_height_max'), 1, height), + filFSelect('weight_min', mt('_charb_weight_min'), 1, weight), + filFSelect('weight_max', mt('_charb_weight_max'), 1, weight), + ], + ontraitpage ? [ mt('_charb_traits'), + [ '', ' ', tag(mt('_charb_traitnothere')) ], + ] : [ mt('_charb_traits'), + [ '', ' ', tag(mt('_js_fil_booland')) ], + filFTagInput('trait_inc', mt('_charb_traitinc'), 'trait'), + filFTagInput('trait_exc', mt('_charb_traitexc'), 'trait'), + filFOptions('tagspoil', ' ', [[0, mt('_charb_spoil0')],[1, mt('_charb_spoil1')],[2, mt('_charb_spoil2')]], + function (o) { var s = getCookie('tagspoil'); if(o+'' == '') return s == null ? 0 : s; setCookie('tagspoil', o); return o}) + ] + ]; +} + function filReleases() { var types = release_types; for(var i=0; i<types.length; i++) // l10n /_rtype_.+/ @@ -2537,8 +2597,8 @@ function filVN() { ] : [ mt('_vnbrowse_tags'), [ '', ' ', tag(mt('_js_fil_booland')) ], [ '', ' ', PREF_CODE != '' ? tag(mt('_vnbrowse_tagactive')) : null ], - filFTagInput('tag_inc', mt('_vnbrowse_taginc')), - filFTagInput('tag_exc', mt('_vnbrowse_tagexc')), + filFTagInput('tag_inc', mt('_vnbrowse_taginc'), 'tag'), + filFTagInput('tag_exc', mt('_vnbrowse_tagexc'), 'tag'), filFOptions('tagspoil', ' ', [[0, mt('_vnbrowse_spoil0')],[1, mt('_vnbrowse_spoil1')],[2, mt('_vnbrowse_spoil2')]], function (o) { var s = getCookie('tagspoil'); if(o+'' == '') return s == null ? 0 : s; setCookie('tagspoil', o); return o}) ], diff --git a/lib/VNDB/DB/Chars.pm b/lib/VNDB/DB/Chars.pm index be620378..634e0078 100644 --- a/lib/VNDB/DB/Chars.pm +++ b/lib/VNDB/DB/Chars.pm @@ -8,7 +8,8 @@ use Exporter 'import'; our @EXPORT = qw|dbCharGet dbCharRevisionInsert dbCharImageId|; -# options: id rev instance traitspoil trait_inc trait_exc char what results page +# options: id rev instance tagspoil trait_inc trait_exc char what results page gender bloodt +# bust_min bust_max waist_min waist_max hip_min hip_max height_min height_max weight_min weight_max # what: extended traits vns changes sub dbCharGet { my $self = shift; @@ -16,7 +17,7 @@ sub dbCharGet { page => 1, results => 10, what => '', - traitspoil => 0, + tagspoil => 0, @_ ); @@ -29,6 +30,18 @@ sub dbCharGet { $o{notid} ? ( 'c.id <> ?' => $o{notid} ) : (), $o{instance} ? ( 'cr.main = ?' => $o{instance} ) : (), $o{vid} ? ( 'cr.id IN(SELECT cid FROM chars_vns WHERE vid = ?)' => $o{vid} ) : (), + defined $o{gender} ? ( 'cr.gender IN(!l)' => [ ref $o{gender} ? $o{gender} : [$o{gender}] ]) : (), + defined $o{bloodt} ? ( 'cr.bloodt IN(!l)' => [ ref $o{bloodt} ? $o{bloodt} : [$o{bloodt}] ]) : (), + defined $o{bust_min} ? ( 'cr.s_bust >= ?' => $o{bust_min} ) : (), + defined $o{bust_max} ? ( 'cr.s_bust <= ? AND cr.s_bust > 0' => $o{bust_max} ) : (), + defined $o{waist_min} ? ( 'cr.s_waist >= ?' => $o{waist_min} ) : (), + defined $o{waist_max} ? ( 'cr.s_waist <= ? AND cr.s_waist > 0' => $o{waist_max} ) : (), + defined $o{hip_min} ? ( 'cr.s_hip >= ?' => $o{hip_min} ) : (), + defined $o{hip_max} ? ( 'cr.s_hip <= ? AND cr.s_hip > 0' => $o{hip_max} ) : (), + defined $o{height_min} ? ( 'cr.height >= ?' => $o{height_min} ) : (), + defined $o{height_max} ? ( 'cr.height <= ? AND cr.height > 0' => $o{height_max} ) : (), + defined $o{weight_min} ? ( 'cr.weight >= ?' => $o{weight_min} ) : (), + defined $o{weight_max} ? ( 'cr.weight <= ? AND cr.weight > 0' => $o{weight_max} ) : (), $o{search} ? ( '(cr.name ILIKE ? OR cr.original ILIKE ? OR cr.alias ILIKE ?)', [ map '%%'.$o{search}.'%%', 1..3 ] ) : (), $o{char} ? ( @@ -37,7 +50,7 @@ sub dbCharGet { '(ASCII(cr.name) < 97 OR ASCII(cr.name) > 122) AND (ASCII(cr.name) < 65 OR ASCII(cr.name) > 90)' => 1 ) : (), $o{trait_inc} ? ( 'c.id IN(SELECT cid FROM traits_chars WHERE tid IN(!l) AND spoil <= ? GROUP BY cid HAVING COUNT(tid) = ?)', - [ ref $o{trait_inc} ? $o{trait_inc} : [$o{trait_inc}], $o{traitspoil}, ref $o{trait_inc} ? $#{$o{trait_inc}}+1 : 1 ]) : (), + [ ref $o{trait_inc} ? $o{trait_inc} : [$o{trait_inc}], $o{tagspoil}, ref $o{trait_inc} ? $#{$o{trait_inc}}+1 : 1 ]) : (), $o{trait_exc} ? ( 'c.id NOT IN(SELECT cid FROM traits_chars WHERE tid IN(!l))' => [ ref $o{trait_exc} ? $o{trait_exc} : [$o{trait_exc}] ] ) : (), ); diff --git a/lib/VNDB/Handler/Chars.pm b/lib/VNDB/Handler/Chars.pm index 9c8a1b5e..c707a453 100644 --- a/lib/VNDB/Handler/Chars.pm +++ b/lib/VNDB/Handler/Chars.pm @@ -451,33 +451,39 @@ sub list { my($self, $fch) = @_; my $f = $self->formValidate( - { get => 'p', required => 0, default => 1, template => 'int' }, - { get => 'q', required => 0, default => '' }, + { get => 'p', required => 0, default => 1, template => 'int' }, + { get => 'q', required => 0, default => '' }, + { get => 'fil', required => 0, default => '' }, ); return $self->resNotFound if $f->{_err}; - my($list, $np) = $self->dbCharGet( + my($list, $np) = $self->filFetchDB(char => $f->{fil}, {}, { $fch ne 'all' ? ( char => $fch ) : (), $f->{q} ? ( search => $f->{q} ) : (), results => 50, page => $f->{p}, what => 'vns', - ); + }); $self->htmlHeader(title => mt '_charb_title'); my $quri = uri_escape($f->{q}); + form action => '/c/all', 'accept-charset' => 'UTF-8', method => 'get'; div class => 'mainbox'; h1 mt '_charb_title'; - form action => '/c/all', 'accept-charset' => 'UTF-8', method => 'get'; - $self->htmlSearchBox('c', $f->{q}); - end; + $self->htmlSearchBox('c', $f->{q}); p class => 'browseopts'; for ('all', 'a'..'z', 0) { a href => "/c/$_?q=$quri", $_ eq $fch ? (class => 'optselected') : (), $_ eq 'all' ? mt('_char_all') : $_ ? uc $_ : '#'; } end; + + a id => 'filselect', href => '#c'; + lit '<i>▸</i> '.mt('_js_fil_filters').'<i></i>'; + end; + input type => 'hidden', class => 'hidden', name => 'fil', id => 'fil', value => $f->{fil}; end; + end 'form'; if(!@$list) { div class => 'mainbox'; diff --git a/lib/VNDB/Handler/Traits.pm b/lib/VNDB/Handler/Traits.pm index f3abdfeb..0a21011c 100644 --- a/lib/VNDB/Handler/Traits.pm +++ b/lib/VNDB/Handler/Traits.pm @@ -27,6 +27,7 @@ sub traitpage { my $f = $self->formValidate( { get => 'p', required => 0, default => 1, template => 'int' }, { get => 'm', required => 0, default => undef, enum => [qw|0 1 2|] }, + { get => 'fil', required => 0, default => '' }, ); return $self->resNotFound if $f->{_err}; my $tagspoil = $self->reqCookie('tagspoil')||''; @@ -83,14 +84,15 @@ sub traitpage { childtags($self, mt('_traitp_childs'), 'i', $t) if @{$t->{childs}}; if(!$t->{meta} && $t->{state} == 2) { - my($chars, $np) = $self->dbCharGet( + my($chars, $np) = $self->filFetchDB(char => $f->{fil}, {}, { trait_inc => $trait, - traitspoil => $f->{m}, + tagspoil => $f->{m}, results => 50, page => $f->{p}, what => 'vns', - ); + }); + form action => "/i$t->{id}", 'accept-charset' => 'UTF-8', method => 'get'; div class => 'mainbox'; h1 mt '_traitp_charlist'; @@ -101,12 +103,17 @@ sub traitpage { a href => "/i$trait?m=2", $f->{m} == 2 ? (class => 'optselected') : (), onclick => "setCookie('tagspoil', 2);return true;", mt '_tagp_spoil2'; end; + a id => 'filselect', href => '#c'; + lit '<i>▸</i> '.mt('_js_fil_filters').'<i></i>'; + end; + input type => 'hidden', class => 'hidden', name => 'fil', id => 'fil', value => $f->{fil}; + if(!@$chars) { p; br; br; txt mt '_traitp_nochars'; end; } p; br; txt mt '_traitp_cached'; end; end 'div'; - + end 'form'; @$chars && $self->charBrowseTable($chars, $np, $f, "/i$trait?m=$f->{m}"); } diff --git a/lib/VNDB/Util/Misc.pm b/lib/VNDB/Util/Misc.pm index 5406fe06..b7df11c3 100644 --- a/lib/VNDB/Util/Misc.pm +++ b/lib/VNDB/Util/Misc.pm @@ -13,11 +13,12 @@ our @EXPORT = qw|filFetchDB ieCheck|; my %filfields = ( vn => [qw|length hasani tag_inc tag_exc taginc tagexc tagspoil lang olang plat ul_notblack ul_onwish ul_voted ul_onlist|], release => [qw|type patch freeware doujin date_before date_after released minage lang olang resolution plat med voiced ani_story ani_ero|], + char => [qw|gender bloodt bust_min bust_max waist_min waist_max hip_min hip_max height_min height_max weight_min weight_max trait_inc trait_exc tagspoil|], ); # Arguments: -# type ('vn' or 'release'), +# type ('vn', 'release' or 'char'), # filter overwrite (string or undef), # when defined, these filters will be used instead of the preferences, # must point to a variable, will be modified in-place with the actually used filters @@ -30,7 +31,7 @@ sub filFetchDB { my($self, $type, $overwrite, $pre, $post) = @_; $pre = {} if !$pre; $post = {} if !$post; - my $dbfunc = $self->can($type eq 'vn' ? 'dbVNGet' : 'dbReleaseGet'); + my $dbfunc = $self->can($type eq 'vn' ? 'dbVNGet' : $type eq 'release' ? 'dbReleaseGet' : 'dbCharGet'); my $prefname = 'filter_'.$type; my $pref = $self->authPref($prefname); diff --git a/util/jsgen.pl b/util/jsgen.pl index f046fe1a..88043162 100755 --- a/util/jsgen.pl +++ b/util/jsgen.pl @@ -111,6 +111,13 @@ sub jsgen { $common .= sprintf "animated = [ %s ];\n", join ', ', @{$S{animated}}; $common .= sprintf "voiced = [ %s ];\n", join ', ', @{$S{voiced}}; $common .= sprintf "vn_lengths = [ %s ];\n", join ', ', @{$S{vn_lengths}}; + $common .= sprintf "blood_types = [ %s ];\n", join ', ', map qq{"$_"}, @{$S{blood_types}}; + $common .= sprintf "genders = [ %s ];\n", join ', ', map qq{"$_"}, @{$S{genders}}; + $common .= sprintf "bust_ranges = [ %s ];\n", join ', ', @{$S{bust_ranges}}; + $common .= sprintf "waist_ranges = [ %s ];\n", join ', ', @{$S{waist_ranges}}; + $common .= sprintf "hip_ranges = [ %s ];\n", join ', ', @{$S{hip_ranges}}; + $common .= sprintf "height_ranges = [ %s ];\n", join ', ', @{$S{height_ranges}}; + $common .= sprintf "weight_ranges = [ %s ];\n", join ', ', @{$S{weight_ranges}}; $common .= sprintf "L10N_LANG = [ %s ];\n", join(', ', map sprintf('["%s","%s"]', $_, $lang{$_}{"_lang_$_"}||$lang{en}{"_lang_$_"}), VNDB::L10N::languages()); |