# Defines define wardrobe.outfit_schedule = ("day", "night", "cloudy", "rainy", "snowy") define wardrobe.subcategories = { "hair": 5, "shirts": 5, "skirts": 5, "pantyhose": 5, "slot1": 5, "panties": 5, "save": 5, "earrings": 4, "sweaters": 4, "trousers": 4, "stockings": 4, "bikini panties": 4, "load": 4, "neckwear": 3, "dresses": 3, "shorts": 3, "socks": 3, "schedule": 3, "one-piece suits": 2, "import": 2, "robes": 1, "export": 1, "gloves": 0, "pubes": 0, "delete": 0, "other": -1, } # Settings default wardrobe.music = True default wardrobe.chitchats = True default wardrobe.autosave = False default wardrobe.suppress_warnings = False default wardrobe.randomize_color = False default wardrobe.global_color = False default wardrobe.allow_opacity = False # Functions init python in wardrobe: from collections import OrderedDict _last_track = None def get_subcategories(d): return OrderedDict( sorted( [ (subcat, [item for item in items if item.unlocked]) for subcat, items in subcategories.get(d, {}).items() ], key=lambda x: subcategories.get(x[0], 0), reverse=True ) ) def get_icon(category): fp = f"gui/creamy_pumpkin_pie/icons/{category}.png" if renpy.loadable(fp): return renpy.store.Image(fp, oversample=4) return renpy.store.Image("gui/creamy_pumpkin_pie/icons/noicon.png", oversample=4) def change_section(section): scope = renpy.get_screen("wardrobe").scope if scope["selected_section"] == section: return scope["selected_section"] = section scope["selected_category"] = None scope["selected_subcategory"] = None def change_category(category): scope = renpy.get_screen("wardrobe").scope if scope["selected_category"] == category: return scope["selected_category"] = category scope["selected_subcategory"] = None def change_subcategory(subcategory): scope = renpy.get_screen("wardrobe").scope if scope["selected_subcategory"] == subcategory: return scope["selected_subcategory"] = subcategory def change_item(item): scope = renpy.get_screen("wardrobe").scope scope["selected_layer"] = 0 scope["layers"] = item.color scope["selected_item"] = item renpy.store.colorpicker.set_layer(item, 0) renpy.restart_interaction() def toggle_setting(setting): if setting == "music": if renpy.store.wardrobe.music == False: renpy.store.wardrobe.music = True renpy.music.play("music/Spring_In_My_Step.ogg") else: renpy.store.wardrobe.music = False renpy.music.play(_last_track, fadein=1) else: # StoreModule is a bit of a hack, but it's the only way to do this. renpy.store.wardrobe.__dict__[setting] = not renpy.store.wardrobe.__dict__[setting] renpy.restart_interaction() def equip(item): scope = renpy.get_screen("wardrobe").scope character = scope["character"] # Check if the item is hair and already equipped if item.type == "hair" and character.is_equipped_item(item): # If so, play a sound and display a notification to indicate that hair cannot be removed renpy.play("sounds/fail.ogg") renpy.notify("Hair cannot be removed.") else: # Check if the item is already equipped if character.is_equipped_item(item): # If so, check if it's possible to unequip the item if wardrobe_check_unequip(item): # If so, play a reaction and then remove the item from the character's equipment wardrobe_react("unequip", item) character.unequip(item) else: # Otherwise, play a failed unequip reaction wardrobe_react("unequip_fail", item) else: # If the item is not already equipped, check if it's possible to equip the item if wardrobe_check_equip(item): # If so, play a reaction and then add the item to the character's equipment wardrobe_react("equip", item) # Check if the item is on the blacklist if not wardrobe_check_blacklist(item): # If so, play a blacklist reaction wardrobe_react("blacklist", item) # Mark the item as seen and equip it to the character item.mark_as_seen() character.equip(item) # Check if a fallback response is required for the item if wardrobe_fallback_required(item): # If so, call the fallback response function renpy.call(get_character_response(states.active_girl, "fallback"), item) else: # Otherwise, play a failed equip reaction wardrobe_react("equip_fail", item) renpy.restart_interaction() def strip(): scope = renpy.get_screen("wardrobe").scope state = scope.get("__character_strip", 0) character = scope["character"] if state == 0: # Strip to underwear character.strip("clothes") character.wear("bra", "panties") scope["__character_strip"] = 1 elif state == 1: # Strip naked character.strip("bra", "panties") scope["__character_strip"] = 2 elif state == 2: # Wear everything character.wear("all") scope["__character_strip"] = 0 renpy.restart_interaction() def exit(): scope = renpy.get_screen("wardrobe").scope character = scope["character"] # Handle exit animation scope["navigation_last_frame_atl"] = renpy.store.navigation_last_frame_hide scope["navigation_atl"] = renpy.store.navigation_hide scope["navigation_exit"] = True # Save the outfit outfit = renpy.store.get_character_outfit(renpy.store.states.active_girl, typ="last") outfit.save() # Reset states character.wear("all") renpy.restart_interaction() # Context label wardrobe(inter_pause=True): $ disable_game_menu() $ wardrobe._last_track = renpy.music.get_playing() if wardrobe.music: play music "music/Spring_In_My_Step.ogg" if inter_pause: # Ensures all irrelevant screens are hidden before capturing the surface tree with Pause(0.2) call screen wardrobe $ enable_game_menu() jump main_room_menu # Interface screen wardrobe(): layer "interface" zorder 0 style_prefix "wardrobe" default navigation_atl = navigation_show default last_frame = (screenshot.capture() or screenshot.image) default navigation_last_frame_atl = navigation_last_frame_show default navigation_exit = False default character = get_character_object(states.active_girl) default selected_section = None default selected_category = None default selected_subcategory = None default selected_item = None default selected_layer = 0 add last_frame at navigation_last_frame_atl add "gui_fade_both" at gui_fade if navigation_exit: timer 0.4 action Return() frame: at navigation_atl vbox: # Sections hbox: spacing 0 button: add wardrobe.get_icon("outfits") xysize (64, 64) tooltip "Outfits" action Function(wardrobe.change_section, "outfits") selected (selected_section == "outfits") button: add wardrobe.get_icon("color_picker") xysize (64, 64) tooltip "Colour Picker" action Function(wardrobe.change_section, "color_picker") selected (selected_section == "color_picker") button: add wardrobe.get_icon("outfits") xysize (64, 64) tooltip "Settings" action Function(wardrobe.change_section, "settings") selected (selected_section == "settings") null height 3 add "frame_spacer" xsize 500 xalign 0.5 null height 3 if selected_section == "outfits": # Categories hbox: spacing 0 for category in character.wardrobe: if category == "hidden": continue button: add wardrobe.get_icon(category) xysize (64, 64) tooltip category action Function(wardrobe.change_category, category) selected (selected_category == category) null height 3 add "frame_spacer" xsize 500 xalign 0.5 null height 3 # Subcategories if selected_category: viewport: ysize 28 edgescroll (60, 50) mousewheel "horizontal" hbox: for subcategory in character.wardrobe[selected_category]: button: label subcategory action Function(wardrobe.change_subcategory, subcategory) selected (selected_subcategory == subcategory) add "frame_spacer" xsize 500 xalign 0.5 null height 5 # Items if selected_subcategory: vpgrid: cols 5 ysize 399 xspacing 5 yspacing 5 mousewheel True scrollbars "vertical" for item in character.wardrobe[selected_category][selected_subcategory]: add item.button elif selected_section == "color_picker": # Included in a single screen because local screen scopes don't work as they should with functions. hbox: # Item list vpgrid: cols 1 ysize 520 yspacing 4 scrollbars "vertical" mousewheel True for state in character.states.values(): $ item = state[0] if item and item.color: button: add AlphaMask(Transform(item.icon, xysize=(48, 48)), Transform("wheelmenu_button_opaque", xysize=(48, 48))) action Function(wardrobe.change_item, item) selected (selected_item == item) if selected_item: $ is_blacklisted = selected_item.type.startswith(tuple(selected_item.blacklist_unequip)) $ is_allowed = selected_item.type.startswith(("makeup", "tattoo")) vbox: label _("Layers") xalign 0.0 hbox: spacing 4 for n, col in enumerate(selected_item.color): button: xysize (32, 32) background col selected_foreground "#ffffff80" action Function(colorpicker.set_layer, selected_item, n) selected (n == selected_layer) # alternate Return(["replace", col]) text str(n+1) hbox: add colorpicker.cp.cpsv xysize (255, 255) add colorpicker.cp.cph xysize (30, 255) if not is_blacklisted and (is_allowed or wardrobe.allow_opacity): add colorpicker.cp.cpa xysize (255, 30) elif selected_section == "settings": textbutton _("Special Music") action Function(wardrobe.toggle_setting, "music") selected wardrobe.music style "wardrobe_checkbox_button" textbutton _("Chitchats") action Function(wardrobe.toggle_setting, "chitchats") selected wardrobe.chitchats style "wardrobe_checkbox_button" textbutton _("Autosave") action Function(wardrobe.toggle_setting, "autosave") selected wardrobe.autosave style "wardrobe_checkbox_button" textbutton _("Suppress Warnings") action Function(wardrobe.toggle_setting, "suppress_warnings") selected wardrobe.suppress_warnings style "wardrobe_checkbox_button" textbutton _("Randomize Colours") action Function(wardrobe.toggle_setting, "randomize_color") selected wardrobe.randomize_color style "wardrobe_checkbox_button" textbutton _("Global Colours") action Function(wardrobe.toggle_setting, "global_color") selected wardrobe.global_color style "wardrobe_checkbox_button" textbutton _("Allow Opacity Slider") action Function(wardrobe.toggle_setting, "allow_opacity") selected wardrobe.allow_opacity style "wardrobe_checkbox_button" add character.image align (1.0, 1.0) zoom 0.6 vbox: align (0.5, 1.0) textbutton "Return" action wardrobe.exit keysym "game_menu" textbutton "Strip" action wardrobe.strip style wardrobe_item_button is empty: background Transform("wheelmenu_button", xysize=(96,96)) hover_background At(Transform("wheelmenu_button_opaque", xysize=(96,96)), wheelmenu_hover_anim) selected_foreground Transform("interface/topbar/icon_check.webp", align=(1.0, 1.0), size=(24, 24)) hover_sound "sounds/qubodup-hover1.ogg" activate_sound "sounds/qubodup-click2.ogg" # anchor (0.5, 0.5) style wardrobe_item_button_inadequate is empty: background Transform("wheelmenu_button", xysize=(96,96)) hover_background At(Transform("wheelmenu_button_opaque", xysize=(96,96), matrixcolor=TintMatrix("#ff0000")), wheelmenu_hover_anim) hover_sound "sounds/qubodup-hover1.ogg" activate_sound "sounds/qubodup-click2.ogg" # anchor (0.5, 0.5) style wardrobe_frame is empty: xsize 540 yfill True padding (10, 10) background Frame(Image("gui/creamy_pumpkin_pie/side_frame.png", oversample=4), 0, 100, 9, 75, tile=False) style wardrobe_button is frame_button: xpadding 0 style wardrobe_button_text is frame_button_text: size 18 style wardrobe_label: xpadding 5 ypadding 2 style wardrobe_label_text is wardrobe_button_text style wardrobe_viewport: fit_first True xsize 500 style wardrobe_checkbox_button: padding (6, 4) hover_background Frame(Image("gui/creamy_pumpkin_pie/book/book_select.png", oversample=4), 20, 0, 20, 0, tile=False) foreground Transform(Image("gui/creamy_pumpkin_pie/book/book_button_check_empty.png", oversample=4), xpos=6, yalign=0.5) selected_foreground Transform(Image("gui/creamy_pumpkin_pie/book/book_button_check_checked.png", oversample=4), xpos=6, yalign=0.5) insensitive_foreground Transform(Image("gui/creamy_pumpkin_pie/book/book_button_check_empty.png", oversample=4), alpha=0.5, xpos=6, yalign=0.5) style wardrobe_checkbox_button_text is wardrobe_button_text: first_indent 24