init 10 python: renpy.config.console = True renpy.config.developer = True renpy.config.quit_action = Quit(confirm=False) renpy.config.keymap['toggle_afm'].append("K_a") renpy.config.keymap['toggle_skip'].remove('K_TAB') # http://www.pygame.org/docs/ref/key.html ## This code ensures that the quick_menu screen is displayed in-game, whenever ## the player has not explicitly hidden the interface. config.overlay_screens.append("quick_menu") def _toggle_quick_menu(): setattr(store, 'suppress_overlay', False) if not hasattr(store,"quick_menu"): setattr(store, 'quick_menu', False) if quick_menu == False: setattr(store, 'quick_menu', True) else: setattr(store, 'quick_menu', False) return config.keymap[ 'toggle_quick_menu' ] = [ 'w' ] config.underlay.append(renpy.Keymap(toggle_quick_menu = Function(_toggle_quick_menu))) init 10: # start.rpy: removes the splashscreens define config.label_overrides = { "splashscreen": "splashscreen_skip" } label splashscreen_skip: return # mod variables default persistent.Fahrenheit = False default persistent.spinning_logo = False default persistent.fps_portraits = False default persistent.xp_numbers = False default persistent.qm_transparency = 0.5 default persistent.qm_buttons = set() if renpy.android else {"save"} default persistent.text_cps = 0 default persistent.afm_time = 10 default persistent.screen_shake = False default persistent.mod_filters = False init 10: # disable screen shakes if persistent.screen_shake: define subtle_screenshake = None define small_screenshake = None define big_screenshake = None define orgasm_shake = None define rumble = None # definitions.rpy: Midday to Afternoon define time_options = ("Morning", "Afternoon", "Evening", "Night", "Late Night") # base.rpy: code below adds the hotkey-toggle to the quick_menu, adds the "Auto" forward button, and slightly adjusts the button colors define quick_menu = True screen quick_menu(): style_prefix "quick" if quick_menu and not (black_screen[0] or renpy.get_screen("Player_menu") or renpy.get_screen("shop_screen") or renpy.get_screen("Wardrobe_screen") or renpy.get_screen("customization_screen")): vbox: if renpy.get_screen("Wardrobe_screen"): align (0.0, 1.0) elif renpy.get_screen("sex_screen"): align (0.86, 1.0) # (0.5, 1.0) else: align (1.0, 1.0) if persistent.large_text_mode: spacing -8 # new spacing setting else: spacing -8 # new spacing setting at Transform(alpha = persistent.qm_transparency) # new transparency setting if config.rollback_enabled and "back" not in persistent.qm_buttons: textbutton _("Back"): action Rollback() if persistent.large_text_mode: text_size 32 # 42 else: text_size 32 if "skip" not in persistent.qm_buttons: textbutton _("Skip"): action Skip() if persistent.large_text_mode: text_size 32 # 42 else: text_size 32 if "pref" not in persistent.qm_buttons: textbutton _("Pref"): action ShowMenu("options") if persistent.large_text_mode: text_size 32 # 42 else: text_size 32 if "save" not in persistent.qm_buttons: textbutton _("Save"): action ShowMenu("save") if persistent.large_text_mode: text_size 32 # 42 else: text_size 32 if "q.save" not in persistent.qm_buttons: textbutton _("Q.Save"): action QuickSave() if persistent.large_text_mode: text_size 32 # 42 else: text_size 32 if "q.load" not in persistent.qm_buttons: textbutton _("Q.Load"): action QuickLoad() if persistent.large_text_mode: text_size 32 # 42 else: text_size 32 if "auto" not in persistent.qm_buttons: textbutton _("Auto"): action Preference("auto-forward", "toggle") if persistent.large_text_mode: text_size 32 # 42 else: text_size 32 style quick_button_text: font "agency_fb.ttf" outlines [(1,"#0000007F")] insensitive_color "#99999966" idle_color "#999999" hover_color "#FFFFFF" selected_idle_color "#CCCCCC" selected_hover_color "#FFFFFF" # base.rpy: removes the quit-confirmation, rearrangement of the menu buttons screen navigation(): use base_button( Return(), pos = (0.820, 0.299), xysize = (int(645*game_resolution), int(194*game_resolution)), padding = (15, 15, 15, 15), button_shadow = True, text = "RETURN") use base_button( ShowMenu("save"), pos = (0.820, 0.3905), xysize = (int(645*game_resolution), int(194*game_resolution)), padding = (15, 15, 15, 15), button_shadow = True, text = "SAVE") use base_button( ShowMenu("load"), pos = (0.820, 0.482), xysize = (int(645*game_resolution), int(194*game_resolution)), padding = (15, 15, 15, 15), button_shadow = True, text = "LOAD") use base_button( ShowMenu("options"), pos = (0.820, 0.5735), xysize = (int(645*game_resolution), int(194*game_resolution)), padding = (15, 15, 15, 15), button_shadow = True, text = "OPTIONS") use base_button( ShowMenu("supporters_screen"), pos = (0.820, 0.665), xysize = (int(645*game_resolution), int(194*game_resolution)), padding = (15, 15, 15, 15), button_shadow = True, text = "CREDITS") use base_button( MainMenu(), pos = (0.820, 0.7565), xysize = (int(645*game_resolution), int(194*game_resolution)), padding = (15, 15, 15, 15), button_shadow = True, text = "MAIN MENU") use base_button( Quit(confirm = False), pos = (0.820, 0.848), xysize = (int(645*game_resolution), int(194*game_resolution)), padding = (15, 15, 15, 15), button_shadow = True, text = "QUIT") # base.rpy: expands the slot buttons, white slot text, more slot info screen file_picker(): default columns = 3 default rows = 6 use menu_background(spinning = True) vbox anchor (0.0, 0.0) pos (0.005, 0.01): # spacing 2 hbox: # spacing 2 use base_button( FilePagePrevious(), padding = (30, 10, 30, 10), text = "<", text_size = 26) for page in ("auto", "quick"): use base_button( FilePage(page), padding = (30, 10, 30, 10), selected = FileCurrentPage() == page, text = page.upper(), text_size = 26) for i in range(1, 21): use base_button( FilePage(i), padding = (30, 10, 30, 10), selected = FileCurrentPage() == f"{i}", text = f"{i}", text_size = 26) use base_button( FilePageNext(), padding = (30, 10, 30, 10), text = ">", text_size = 26) null height 8 grid columns rows pos (0.005, 0.01) xsize 0.8: style_prefix "file_picker" transpose True xfill True spacing 5 for i in range(1, columns*rows + 1): $ file_name = FileSlotName(i, columns * rows) $ file_time = FileTime(i, format=_("{#file_time}%a, %b %d %Y, %H:%M"), empty = _("EMPTY")) # https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior $ save_name = FileSaveName(i) button ysize 0.155: xfill True hbox align (0.0, 0.5): spacing 15 add FileScreenshot(i) yalign 0.5 text "[file_name].\n[save_name!ti]\n[file_time!t]": font "agency_fb.ttf" size 23 color "#fff" text_align 0.0 if save_name: if renpy.android: use base_button( FileDelete(i), anchor = (1.0, 0.0), pos = (1.02, 0.0), xysize = (int(192*0.4), int(194*0.4)), padding = (15, 15, 15, 15), button_shadow = True, image = "images/interface/[interface_resolution]/interactions/close.webp", image_zoom = 0.4, image_shadow = True, animated = False) else: use base_button( FileDelete(i), anchor = (1.0, 0.0), pos = (1.02, 0.0), xysize = (int(192*0.25), int(194*0.25)), padding = (15, 15, 15, 15), button_shadow = True, image = "images/interface/[interface_resolution]/interactions/close.webp", image_zoom = 0.25, image_shadow = True, animated = False) key "save_delete" action FileDelete(i) action FileAction(i) # main_menu.rpy: removes the quit-confirmation screen main_menu(): tag menu add Solid("#363535") xysize (1.0, 1.0) use menu_background(characters = True, spinning = True) add "images/interface/[interface_resolution]/main_menu/small_elements.webp" zoom interface_adjustment add "images/interface/[interface_resolution]/main_menu/big_elements.webp" zoom interface_adjustment add "images/interface/[interface_resolution]/main_menu/game_version.webp" zoom interface_adjustment add "images/interface/[interface_resolution]/main_menu/logo.webp" zoom high_resolution_interface_adjustment add "menu_comic" text "GAME VERSION" anchor (0.0, 0.5) pos (0.025, 0.96): size 25 text "[config.version]" anchor (1.0, 0.5) pos (0.157, 0.96): size 25 if config.version != "0.8b1": text "{color=#D92912}with incompatible TNHUXMod v0.8b1.15{/color}" anchor (1.0, 0.5) pos (0.345, 0.96): size 25 else: text "{color=#FFA920}with TNHUXMod v0.8b1.15{/color}" anchor (1.0, 0.5) pos (0.284, 0.96): size 25 use base_button( OpenURL("https://patreon.com/ronchon"), pos = (0.712, 0.868), xysize = (int(192*game_resolution), int(194*game_resolution)), button_shadow = True, image = "images/interface/[interface_resolution]/main_menu/patreon.webp", image_zoom = high_resolution_interface_adjustment, image_shadow = True) use base_button( OpenURL("https://soundcloud.com/grey_scale"), pos = (0.768, 0.868), xysize = (int(192*game_resolution), int(194*game_resolution)), button_shadow = True, image = "images/interface/[interface_resolution]/main_menu/soundcloud.webp", image_zoom = high_resolution_interface_adjustment, image_shadow = True) use base_button( OpenURL("https://discord.gg/kFjf49QVns"), pos = (0.824, 0.868), xysize = (int(192*game_resolution), int(194*game_resolution)), button_shadow = True, image = "images/interface/[interface_resolution]/main_menu/discord.webp", image_zoom = high_resolution_interface_adjustment, image_shadow = True) use base_button( Quit(confirm = False), pos = (0.88, 0.868), xysize = (int(192*game_resolution), int(194*game_resolution)), button_shadow = True, image = "images/interface/[interface_resolution]/interactions/close.webp", image_zoom = high_resolution_interface_adjustment, image_shadow = True) use base_button( Start(), pos = (0.164, 0.47), xysize = (int(839*game_resolution), int(194*game_resolution)), button_shadow = True, text = "NEW GAME", text_size = 45) use base_button( Continue(), pos = (0.164, 0.573), xysize = (int(627*game_resolution), int(194*game_resolution)), button_shadow = True, text = "CONTINUE", text_size = 45) use base_button( ShowMenu("load"), pos = (0.332, 0.573), xysize = (int(192*game_resolution), int(194*game_resolution)), button_shadow = True, image = "images/interface/[interface_resolution]/main_menu/load.webp", image_zoom = high_resolution_interface_adjustment, image_shadow = True) use base_button( ShowMenu("options"), pos = (0.164, 0.676), xysize = (int(839*game_resolution), int(194*game_resolution)), button_shadow = True, text = "OPTIONS", text_size = 45) # base.rpy: removes the spinning X-logo screen menu_background(characters = False, spinning = False): layer "master" add Solid("#363535") xysize (1.0, 1.0) if characters: add "characters_background" zoom interface_adjustment if not persistent.spinning_logo: add "images/interface/[interface_resolution]/main_menu/spin.webp" align (0.5, 0.5) zoom interface_adjustment: if persistent.animated_interface and spinning: at spin add "images/interface/[interface_resolution]/main_menu/overlay.webp" zoom interface_adjustment # hotkeys.rpy: game hotkeys. Changes here should also be made to: screen options() screen hotkeys1_screen(): if persistent.volume_muted: key "-" action [ SetVariable("persistent.volume_muted", False), SetMute(["sfx", "music"], False)] # - else: key "-" action [ SetVariable("persistent.volume_muted", True), SetMute(["sfx", "music"], True)] # - key "K_RETURN" action DisableAllInputValues() screen hotkeys2_screen(): key "p" action ToggleScreen("phone_screen") # p key "t" action ToggleScreen("remote_vibrator_screen") # t if Player.location != Player.home: key "r" action Call("travel", Player.home) # r if Player.location != "bg_classroom": key "c" action Call("travel", "bg_classroom") # c if Player.location != "bg_danger": key "g" action Call("travel", "bg_danger") # g if Player.schedule or Player.date_planned: key "q" action Show("say", who = None, what = "I've got plans today.", hide_after = 3.0) # q elif black_screen[0] or not sandbox or ongoing_Event or ongoing_Scene or renpy.get_screen("Player_menu") or renpy.get_screen("shop_screen") or renpy.get_screen("Wardrobe_screen") or renpy.get_screen("customization_screen") or renpy.get_screen("phone_screen") or renpy.get_screen("sex_screen"): key "q" action Show("say", who = None, what = "I shouldn't skip now.", hide_after = 3.0) # q else: key "q" action Call("go_to_sleep", automatic = True, from_current = True) # q if quick_location_1: key "1" action Function(quick_location_1.exec) # 1 if quick_location_2: key "2" action Function(quick_location_2.exec) # 2 if quick_location_3: key "3" action Function(quick_location_3.exec) # 3 # new "Xavier's Study" hotkey if Player.location != "bg_study": key "x" action Call("travel", "bg_study") # x # new "Mall" hotkey if Player.location != "bg_mall": key "l" action Call("travel", "bg_mall") # l # new "Kitchen" hotkey if Player.location != "bg_kitchen": key "k" action Call("travel", "bg_kitchen") # k # new "Pool" hotkey if Player.location != "bg_pool": key "o" action Call("travel", "bg_pool") # o screen hotkeys3_screen(): key "mousedown_3" action [ Hide("phone_screen"), Hide("Wardrobe_screen"), ToggleScreen("Player_menu", page = "map")] screen hotkeys4_screen(): key "i" action ToggleScreen("Player_menu", page = "inventory") key "j" action ToggleScreen("Player_menu", page = "journal") key "m" action ToggleScreen("Player_menu", page = "map") # belt.rpy: thousands separator, daily income display, and Celcius-Fahrenheit toggle for player belt, remote button only shown if remote vibrator inserted in any character screen belt_screen(): add "images/interface/[interface_resolution]/belt/background.webp" zoom interface_adjustment add "images/interface/[interface_resolution]/belt/stamina.webp" zoom high_resolution_interface_adjustment imagebutton: idle At(f"images/interface/{interface_resolution}/belt/hide_idle.webp", interface_zoom) hover At(f"images/interface/{interface_resolution}/belt/hide.webp", interface_zoom) action ToggleVariable("belt_collapsed") tooltip "Hide Belt" text "[week[weekday][0:2]]" anchor (0.5, 0.5) pos (0.9635, 0.04): # pos (0.964, 0.075) font "magneto_bold.ttf" size 40 text "[time_options[time_index]]" anchor (0.5, 0.5) pos (0.9635, 0.075): # pos (0.964, 0.075) size 28 # 30 hbox anchor (1.0, 0.5) pos (0.822, 0.0345) ysize int(99*game_resolution): spacing 6 box_reverse True if Player.History.check("attended_class", tracker = "weekly") >= 3: imagebutton: idle At(f"images/interface/{interface_resolution}/belt/attendance.webp", high_resolution_interface_zoom) hover At(f"images/interface/{interface_resolution}/belt/attendance.webp", high_resolution_interface_zoom) action NullAction() tooltip "Attendance Bonus" if Player.sweat >= Player.sweaty_threshold or Player.chlorine >= Player.chlorinated_threshold: imagebutton: idle At(f"images/interface/{interface_resolution}/belt/sweaty.webp", high_resolution_interface_zoom) hover At(f"images/interface/{interface_resolution}/belt/sweaty.webp", high_resolution_interface_zoom) action NullAction() tooltip "Sweaty" else: imagebutton: idle At(f"images/interface/{interface_resolution}/belt/neutral.webp", high_resolution_interface_zoom) hover At(f"images/interface/{interface_resolution}/belt/neutral.webp", high_resolution_interface_zoom) action NullAction() tooltip "Neutral" if Party: imagebutton: idle At(f"images/interface/{interface_resolution}/belt/followed.webp", high_resolution_interface_zoom) hover At(f"images/interface/{interface_resolution}/belt/followed.webp", high_resolution_interface_zoom) action NullAction() tooltip "Being Followed" hbox anchor (0.5, 0.5) pos (0.8925, 0.035) ysize 0.241: for s in range(Player.max_stamina): if s >= clock: imagebutton: idle At(f"images/interface/{interface_resolution}/belt/stamina_empty.webp", interface_zoom) hover At(f"images/interface/{interface_resolution}/belt/stamina_empty.webp", interface_zoom) action NullAction() tooltip "Stamina (Empty)" else: imagebutton: idle At(f"images/interface/{interface_resolution}/belt/stamina_full.webp", interface_zoom) hover At(f"images/interface/{interface_resolution}/belt/stamina_full.webp", interface_zoom) action NullAction() tooltip "Stamina" for s in range(Player.max_stamina, 4): imagebutton: idle At(f"images/interface/{interface_resolution}/belt/stamina_lock.webp", high_resolution_interface_zoom) hover At(f"images/interface/{interface_resolution}/belt/stamina_lock.webp", high_resolution_interface_zoom) action NullAction() tooltip "Stamina (Locked)" text "$['{:,}'.format(Player.cash)]+[Player.income]/day" anchor (1.0, 0.5) pos (0.862, 0.0815): size 25 # Celcius-Fahrenheit toggle key "d" action ToggleVariable("persistent.Fahrenheit") if persistent.Fahrenheit: text u"['{:.1f}'.format(temperature[time_index]*9/5+32)] \u00b0F" anchor (0.5, 0.5) pos (0.903, 0.0815): size 25 else: text u"[temperature[time_index]] \u00b0C" anchor (0.5, 0.5) pos (0.903, 0.0815): size 25 if not belt_collapsed: $ buttons_locked = (not idling or renpy.get_screen("say") or ongoing_Scene or phone_texting) $ button_condition = (not current_phone_Chat or not current_phone_Chat.mandatory_text_options) $ buttons = ["inventory", "journal", "map"] if Player.Inventory.get_active("phone"): $ buttons.append("phone") # check if remote vibrator inserted in any character if Player.Inventory.get_active("remote_vibrator_controller") and get_remote_vibrator_Characters() != (): $ buttons.append("remote") for t, kind in enumerate(buttons): if kind == "inventory": $ hotkey = "I" elif kind == "journal": $ hotkey = "J" elif kind == "map": $ hotkey = "M" elif kind == "phone": $ hotkey = "P" elif kind == "remote": $ hotkey = "T" if buttons_locked: $ actions = None $ tooltip = None elif button_condition: if kind in ["map"]: $ actions = Show("Player_menu", page = kind) elif kind in ["phone"]: if not renpy.get_screen("phone_screen"): $ actions = [ Show("phone_screen"), SetVariable("phone_alert", False)] else: $ actions = [ Hide("phone_screen"), Function(move_location, Player.location)] elif kind in ["remote"]: $ actions = ToggleScreen("remote_vibrator_screen") else: $ actions = [ Show("Player_menu", page = kind), SetVariable(f"{kind}_alert", False)] $ tooltip = f"Open {titlize(kind)}" if buttons_locked or button_condition: use belt_button( actions, pos = (0.9323, 0.103 + t*0.131), xysize = (int(237*game_resolution), int(281*game_resolution)), text = f"Hotkey: {hotkey}", image = f"images/interface/{interface_resolution}/belt/{kind}.webp", image_zoom = high_resolution_interface_adjustment, image_shadow = True, tooltip = tooltip) if sandbox: for q, quick_location in enumerate([quick_location_1, quick_location_2, quick_location_3]): if quick_location: if buttons_locked: $ actions = NullAction() $ tooltip = None elif button_condition: $ actions = Function(quick_location.exec) $ tooltip = f"Move to QuickLoc{q + 1}" if buttons_locked or button_condition: use quick_button( actions, pos = (0.907, 0.369 + q*0.042), xysize = (int(87*game_resolution), int(87*game_resolution)), text = f"{q + 1}", tooltip = tooltip) if button_condition: if inventory_alert: add "images/interface/[interface_resolution]/belt/inventory_alert.webp" anchor (0.5, 0.5) pos (0.935, 0.108) zoom high_resolution_interface_adjustment if journal_alert: add "images/interface/[interface_resolution]/belt/red_alert.webp" anchor (0.5, 0.5) pos (0.935, 0.239) zoom high_resolution_interface_adjustment if map_alert: add "images/interface/[interface_resolution]/belt/red_alert.webp" anchor (0.5, 0.5) pos (0.935, 0.37) zoom high_resolution_interface_adjustment if Player.Inventory.get_active("phone"): if phone_alert or unread_messages or institute_broadcast: add "images/interface/[interface_resolution]/belt/phone_alert.webp" anchor (0.5, 0.5) pos (0.935, 0.502) zoom high_resolution_interface_adjustment if persistent.tooltips_enabled: use tooltips() # remote_vibrator.rpy: screen only shown when at least one remote vibrator inserted in any character screen remote_vibrator_screen(): default index = 0 layer "interface" # check if remote vibrator inserted in any character if black_screen[0] or get_remote_vibrator_Characters() == (): pass elif any(renpy.get_screen(screen) for screen in remote_vibrator_disabled_screens): pass elif ongoing_Event: pass else: $ Characters = get_remote_vibrator_Characters() if index > len(Characters) - 1: $ index = 0 $ button_condition = (idling and (not current_phone_Chat or not current_phone_Chat.mandatory_text_options)) add "images/interface/[interface_resolution]/belt/remote_background.webp" zoom high_resolution_interface_adjustment if button_condition: if Characters and Characters[index].remote_vibrator: bar value VariableValue(f"{Characters[index].tag}.remote_vibrator", 1.0) anchor (0.5, 0.5) pos (0.846, 0.800) xysize (int(275*game_resolution), int(48*game_resolution)): left_bar At(f"images/interface/{interface_resolution}/belt/remote_intensity.webp", interface_zoom) right_bar At(f"images/interface/{interface_resolution}/belt/remote_intensity.webp", interface_zoom) thumb Frame("images/interface/full/belt/remote_selector.webp") thumb_offset int(17*game_resolution) else: bar value 0.0 range 1.0 anchor (0.5, 0.5) pos (0.846, 0.800) xysize (int(275*game_resolution), int(48*game_resolution)): left_bar At(f"images/interface/{interface_resolution}/belt/remote_intensity.webp", interface_zoom) right_bar At(f"images/interface/{interface_resolution}/belt/remote_intensity.webp", interface_zoom) thumb Frame("images/interface/full/belt/remote_selector.webp") thumb_offset int(17*game_resolution) else: if Characters and Characters[index].remote_vibrator: bar value Characters[index].remote_vibrator range 1.0 anchor (0.5, 0.5) pos (0.846, 0.800) xysize (int(275*game_resolution), int(48*game_resolution)): left_bar At(f"images/interface/{interface_resolution}/belt/remote_intensity.webp", interface_zoom) right_bar At(f"images/interface/{interface_resolution}/belt/remote_intensity.webp", interface_zoom) thumb Frame("images/interface/full/belt/remote_selector.webp") thumb_offset int(17*game_resolution) else: bar value 0.0 range 1.0 anchor (0.5, 0.5) pos (0.846, 0.800) xysize (int(275*game_resolution), int(48*game_resolution)): left_bar At(f"images/interface/{interface_resolution}/belt/remote_intensity.webp", interface_zoom) right_bar At(f"images/interface/{interface_resolution}/belt/remote_intensity.webp", interface_zoom) thumb Frame("images/interface/full/belt/remote_selector.webp") thumb_offset int(17*game_resolution) if Characters: if button_condition: if Characters[index].remote_vibrator == 0.0: $ actions = [SetField(Characters[index], "remote_vibrator", 0.1)] if renpy.random.random() > 0.8: $ actions.append(Call("remote_vibrator", Characters[index], "on", from_current = True)) else: $ actions = [SetField(Characters[index], "remote_vibrator", 0.0)] if renpy.random.random() > 0.8: $ actions.append(Call("remote_vibrator", Characters[index], "off", from_current = True)) else: $ actions = NullAction() else: $ actions = None imagebutton: idle At(f"images/interface/{interface_resolution}/belt/remote_off.webp", interface_zoom) hover At(f"images/interface/{interface_resolution}/belt/remote_on.webp", interface_zoom) selected_idle At(f"images/interface/{interface_resolution}/belt/remote_on.webp", interface_zoom) selected Characters and Characters[index].remote_vibrator action actions imagebutton: idle At(f"images/interface/{interface_resolution}/belt/remote_left_idle.webp", interface_zoom) hover At(f"images/interface/{interface_resolution}/belt/remote_left.webp", interface_zoom) if Characters: if button_condition: action SetScreenVariable("index", (index - 1) % len(Characters)) else: action NullAction() else: action None if Characters: text "[Characters[index].name]" anchor (0.5, 0.5) pos (0.846, 0.699): size 25 imagebutton: idle At(f"images/interface/{interface_resolution}/belt/remote_right_idle.webp", interface_zoom) hover At(f"images/interface/{interface_resolution}/belt/remote_right.webp", interface_zoom) if Characters: if button_condition: action SetScreenVariable("index", (index + 1) % len(Characters)) else: action NullAction() else: action None if renpy.get_screen("say") or phone_texting: button xysize (1.0, 1.0): background None hover_sound None activate_sound None action Return() # shop.rpy: thousands separator for shops screen shop_screen(shop_type, discount = 1.0, unrestricted = False): default page = 0 default Item = None default cart = [] default bought_something = False layer "interface" on "show" action Function(hide_Characters_for_interface, Present) on "hide" action Function(show_Characters_for_interface, Present) if black_screen[0]: pass elif renpy.get_screen("options"): pass else: if persistent.animated_interface: timer 1.0 action ToggleVariable("interface_blinking") repeat True modal True $ inventory = list(get_shop_inventory(shop_type, unrestricted = unrestricted).values()) if Player.check_traits("charming_personality"): $ discount *= 0.9 use menu_background(spinning = True) add "images/interface/[interface_resolution]/shop/background.webp" zoom interface_adjustment add "images/interface/[interface_resolution]/shop/cash.webp" zoom interface_adjustment add "images/interface/[interface_resolution]/shop/panels.webp" zoom interface_adjustment add "images/interface/[interface_resolution]/shop/tab.webp" zoom interface_adjustment add "images/interface/[interface_resolution]/shop/total.webp" zoom interface_adjustment if shop_type == "clothing": add "images/interface/[interface_resolution]/shop/mutant_couture.webp" zoom high_resolution_interface_adjustment elif shop_type == "gift": add "images/interface/[interface_resolution]/shop/bear_with_me.webp" zoom high_resolution_interface_adjustment elif shop_type == "lingerie": add "images/interface/[interface_resolution]/shop/xtreme_intimates.webp" zoom high_resolution_interface_adjustment elif shop_type == "sex": add "images/interface/[interface_resolution]/shop/moaning_of_life.webp" zoom high_resolution_interface_adjustment if len(inventory) > 7: $ actions = SetScreenVariable("page", (page - 1) % math.ceil(len(inventory)/7)) else: $ actions = None use shop_tab_button( actions, anchor = (0.0, 0.0), pos = (0.058, 0.637), xysize = (int(194*game_resolution), int(105*game_resolution)), image = f"images/interface/{interface_resolution}/shop/left.webp", image_zoom = high_resolution_interface_adjustment) if len(inventory) > 7: $ actions = SetScreenVariable("page", (page + 1) % math.ceil(len(inventory)/7)) else: $ actions = None use shop_tab_button( actions, anchor = (0.0, 0.0), pos = (0.268, 0.637), xysize = (int(194*game_resolution), int(105*game_resolution)), image = f"images/interface/{interface_resolution}/shop/right.webp", image_zoom = high_resolution_interface_adjustment) if page < 9: $ page_number = f"0{page + 1}" else: $ page_number = f"{page + 1}" if math.ceil(len(inventory)/7) == 0: $ max_page_number = "" elif math.ceil(len(inventory)/7) < 9: $ max_page_number = f"/0{math.ceil(len(inventory)/7)}" else: $ max_page_number = f"/{math.ceil(len(inventory)/7)}" if interface_blinking: text "TAB{alpha=0.0}_{/alpha}[page_number][max_page_number]" anchor (0.5, 0.5) pos (0.186, 0.661): size 35 else: text "TAB_[page_number][max_page_number]" anchor (0.5, 0.5) pos (0.186, 0.661): size 35 vbox anchor (0.5, 0.0) pos (0.546, 0.315) xysize (0.41, 0.6): spacing -5 for i in range(7*page, 7*page + 7): if i > len(inventory) - 1: continue $ I = inventory[i] $ quantity = 0 $ removable_Item = None for I_temp in cart: if I.Owner == I_temp.Owner and I.string == I_temp.string: $ quantity += 1 $ removable_Item = I_temp fixed xysize (1.0, int(177*game_resolution)): button anchor (0.0, 0.5) pos (0.0, 0.5) xysize (int(884*game_resolution), int(135*game_resolution)): idle_background At(f"images/interface/{interface_resolution}/shop/item_idle.webp", interface_zoom) hover_background At(f"images/interface/{interface_resolution}/shop/item.webp", interface_zoom) selected_idle_background At(f"images/interface/{interface_resolution}/shop/item.webp", interface_zoom) selected Item and Item.Owner == I.Owner and Item.string == I.string action SetScreenVariable("Item", I) text f"{titlize(I.name, only_first = False)}" anchor (0.0, 0.5) pos (0.02, 0.5): font "agency_fb.ttf" size 30 add "images/interface/[interface_resolution]/shop/price.webp" anchor (0.5, 0.5) pos (0.6735, 0.5) zoom interface_adjustment if discount != 1.0: $ discounted_price = int(discount*I.price) text "${s}[I.price]{/s} [discounted_price]" anchor (0.5, 0.5) pos (0.6735, 0.5): size 30 else: text "$[I.price]" anchor (0.5, 0.5) pos (0.6735, 0.5): size 30 $ actions = None if I.Owner not in {None, Player}: if not check_cart(cart, f"{I.Owner}_{I.string}"): $ actions = AddToSet(cart, I) elif isinstance(I.unlocked, list): if not check_cart(cart, I.string, unlocked = I.unlocked): $ actions = AddToSet(cart, I) else: $ actions = AddToSet(cart, I) use shop_amount_button( actions, anchor = (0.5, 0.5), pos = (0.8068, 0.5), xysize = (int(107*game_resolution), int(135*game_resolution)), image = f"images/interface/{interface_resolution}/shop/plus.webp", image_zoom = high_resolution_interface_adjustment) add "images/interface/[interface_resolution]/shop/quantity.webp" anchor (0.5, 0.5) pos (0.88, 0.5) zoom interface_adjustment text "[quantity]" anchor (0.5, 0.5) pos (0.88, 0.5): size 30 if removable_Item: $ actions = RemoveFromSet(cart, removable_Item) else: $ actions = None use shop_amount_button( actions, anchor = (1.0, 0.5), pos = (0.9855, 0.5), xysize = (int(107*game_resolution), int(135*game_resolution)), image = f"images/interface/{interface_resolution}/shop/minus.webp", image_zoom = high_resolution_interface_adjustment) text "CASH{alpha=0.0}_{/alpha}" anchor (0.0, 0.5) pos (0.065, 0.586): size 36 text "$['{:,}'.format(Player.cash)]" anchor (1.0, 0.5) pos (0.318, 0.586): size 36 $ total_cost = 0 for I in cart: $ total_cost += I.price $ total_cost = int(total_cost*discount) text "TOTAL{alpha=0.0}_{/alpha}" anchor (0.0, 0.5) pos (0.505, 0.91): size 36 text "$['{:,}'.format(total_cost)]" anchor (1.0, 0.5) pos (0.745, 0.91): size 36 imagebutton: idle At(f"images/interface/{interface_resolution}/shop/buy_idle.webp", interface_zoom) hover At(f"images/interface/{interface_resolution}/shop/buy.webp", interface_zoom) if cart and Player.cash >= total_cost: action [ SetScreenVariable("bought_something", True), Function(buy_cart, cart = cart, discount = discount), SetScreenVariable("cart", []), SetVariable("inventory_alert", True)] else: action None tooltip "Buy Cart" text "BUY" anchor (0.5, 0.5) pos (0.367, 0.91): size 36 imagebutton: idle At(f"images/interface/{interface_resolution}/shop/clear_idle.webp", interface_zoom) hover At(f"images/interface/{interface_resolution}/shop/clear.webp", interface_zoom) action SetScreenVariable("cart", []) tooltip "Clear Cart" text "CLEAR" anchor (0.5, 0.5) pos (0.445, 0.91): size 36 imagebutton: idle At(f"images/interface/{interface_resolution}/shop/quit_idle.webp", interface_zoom) hover At(f"images/interface/{interface_resolution}/shop/quit.webp", interface_zoom) action Return(bought_something) tooltip "Exit" text "DONE" anchor (0.0, 0.5) pos (0.065, 0.738): size 36 text "ITEM DESCRIPTION{alpha=0.0}_{/alpha}" anchor (0.0, 0.5) pos (0.776, 0.336): size 36 text "TRACKER{alpha=0.0}_{/alpha}" anchor (0.0, 0.5) pos (0.776, 0.683): size 36 text "OWNED{alpha=0.0}_{/alpha}" anchor (0.0, 0.5) pos (0.776, 0.91): size 36 if Item: if isinstance(Item, ItemClass): text "[Item.description]" anchor (0.5, 0.5) pos (0.851, 0.507) xysize (0.159, 0.235): size 30 if shop_type in {"clothing", "lingerie"}: add "images/interface/full/icons/[Item.Owner.tag].webp" anchor (0.5, 0.5) pos (0.851, 0.797) zoom 0.5 else: vpgrid anchor (0.5, 0.5) pos (0.8555, 0.805) xysize (0.16, 0.12): cols 5 spacing 10 draggable True mousewheel True if Item.filter_type == "key_gifts": for C in Item.unlocked: fixed xysize (int(0.2*252), int(0.2*252)): add "images/interface/full/icons/[C].webp" zoom 0.2 if getattr(store, C).Inventory.get(Item.string): add "images/interface/[interface_resolution]/interactions/gift.webp" align (1.0, 1.0) zoom 0.2 else: for C in get_Item_Characters(Item): fixed xysize (int(0.2*252), int(0.2*252)): if approval_check(C, threshold = C.gift_thresholds.get(Item.string, (0, 0))): if shop_type == "gift" and Item.string not in C.gift_bonuses: add "images/interface/full/icons/[C.tag].webp" zoom 0.2 matrixcolor matrix_colors["black_and_white"] else: add "images/interface/full/icons/[C.tag].webp" zoom 0.2 else: add "images/interface/full/icons/[C.tag].webp" zoom 0.2 matrixcolor matrix_colors["black_and_white"] if C.Inventory.get(Item.string): add "images/interface/[interface_resolution]/interactions/gift.webp" align (1.0, 1.0) zoom 0.2 text "[Player.Inventory.get_number(Item.string)]" anchor (1.0, 0.5) pos (0.926, 0.91): size 36 if black_screen[0] or renpy.get_screen("say"): button xysize (1.0, 1.0): background None hover_sound None activate_sound None if not renpy.get_screen("choice"): action Return() else: action NullAction() use quick_menu() if persistent.tooltips_enabled: use tooltips() # Player_menu.rpy: thousands separator for inventory screen inventory_screen(giving_gift): default inventory_page = 0 default inventory_filter = "gift" default inventory_Item = None $ Item_list = [] for Item_string in Player.Inventory.Items: for I in Player.Inventory.Items[Item_string]: if inventory_filter == "gift" and isinstance(I, ClothingClass): $ Item_list.append(Item_string) elif isinstance(I, ItemClass): if Item_string in Item_list: continue if inventory_filter not in I.filter_type: continue if I.Owner == Player and inventory_filter == "key": $ Item_list.append(Item_string) elif I.Owner != Player and inventory_filter == "gift": $ Item_list.append(Item_string) add "images/interface/[interface_resolution]/Player_menu/inventory_background.webp" zoom interface_adjustment add "images/interface/[interface_resolution]/Player_menu/inventory_cash.webp" zoom interface_adjustment add "images/interface/[interface_resolution]/Player_menu/inventory_description.webp" zoom interface_adjustment add "images/interface/[interface_resolution]/Player_menu/inventory_name.webp" zoom interface_adjustment if math.floor(len(Item_list)/15) > 0: add "images/interface/[interface_resolution]/Player_menu/inventory_pages.webp" zoom interface_adjustment use inventory_page( SetLocalVariable("inventory_page", (inventory_page - 1) % math.ceil(len(Item_list)/15)), pos = (0.056, 0.205), xysize = (int(372*game_resolution), int(124*game_resolution)), image = "images/interface/[interface_resolution]/Player_menu/inventory_left.webp", image_zoom = high_resolution_interface_adjustment, image_shadow = True) if inventory_page < 9: if interface_blinking: text "TAB{alpha=0.0}_{/alpha}0[inventory_page + 1]" anchor (0.5, 0.5) pos (0.199, 0.234): size 35 else: text "TAB_0[inventory_page + 1]" anchor (0.5, 0.5) pos (0.199, 0.234): size 35 else: if interface_blinking: text "TAB{alpha=0.0}_{/alpha}[inventory_page + 1]" anchor (0.5, 0.5) pos (0.199, 0.234): size 35 else: text "TAB_[inventory_page + 1]" anchor (0.5, 0.5) pos (0.199, 0.234): size 35 use inventory_page( SetLocalVariable("inventory_page", (inventory_page + 1) % math.ceil(len(Item_list)/15)), pos = (0.250, 0.205), xysize = (int(372*game_resolution), int(124*game_resolution)), image = "images/interface/[interface_resolution]/Player_menu/inventory_right.webp", image_zoom = high_resolution_interface_adjustment, image_shadow = True) grid 5 3 anchor (0.0, 0.0) pos (0.065, 0.319) xysize (0.6, 0.7): xspacing 9 yspacing 7 for i in range(15*inventory_page, min(15*(inventory_page + 1), len(Item_list))): if inventory_filter == "key": $ Owner = Player elif giving_gift: $ Owner = None else: $ Owner = False $ I = Player.Inventory.get(Item_list[i], filter = inventory_filter, Owner = Owner) $ actions = [SetLocalVariable("inventory_Item", I)] if giving_gift: if isinstance(I, ClothingClass): if I.Owner == focused_Character: $ actions.append(Show("confirm_gift_screen", Character = focused_Character, Item = I)) elif isinstance(I, ItemClass): if not renpy.has_label(f"{focused_Character.tag}_{I.tag}_gift_accept") and not renpy.has_label(f"{focused_Character.tag}_{I.tag}_accept"): $ actions.append(Show("cannot_gift_screen", Character = focused_Character, Item = I)) elif ("piercing" in I.string or "plug" in I.string or "vibrator" in I.string) and focused_Character.Inventory.get(I.string): $ actions.append(Show("cannot_gift_screen", Character = focused_Character, Item = I)) elif isinstance(I.unlocked, list): if focused_Character.tag in I.unlocked: $ actions.append(Show("confirm_gift_screen", Character = focused_Character, Item = I)) elif I.Owner and I.Owner != Character: pass elif I.Owner != Player: $ actions.append(Show("confirm_gift_screen", Character = focused_Character, Item = I)) button xysize (int(426*game_resolution), int(426*game_resolution)): if inventory_Item == I: background At(f"images/interface/{interface_resolution}/Player_menu/inventory_selector.webp", interface_zoom) else: background None hover_sound None if isinstance(I, ClothingClass): if I.shop_type == "clothing": add "images/interface/[interface_resolution]/items/mutant_couture.webp" anchor (0.5, 0.5) pos (0.5, 0.4) zoom 0.2*interface_adjustment elif I.shop_type == "lingerie": add "images/interface/[interface_resolution]/items/xtreme_intimates.webp" anchor (0.5, 0.5) pos (0.5, 0.4) zoom 0.2*interface_adjustment add "images/interface/full/icons/[I.Owner.tag].webp" anchor (0.5, 0.5) pos (0.91, 0.857) zoom 0.18 elif isinstance(I, ItemClass): if "piercing" in I.string: add "images/interface/[interface_resolution]/items/piercings.webp" anchor (0.5, 0.5) pos (0.5, 0.4) zoom 0.2*interface_adjustment else: add "images/interface/[interface_resolution]/items/[I.image].webp" anchor (0.5, 0.5) pos (0.5, 0.4) zoom 0.2*interface_adjustment if Player.Inventory.get_number(I.string, filter = inventory_filter, Owner = Owner) > 1: text "x[Player.Inventory.get_number(I.string, filter = inventory_filter, Owner = Owner)]" anchor (0.5, 1.0) pos (0.5, 0.95): size 32 if giving_gift and focused_Character.Inventory.get(I.string): add "images/interface/[interface_resolution]/interactions/gift.webp" anchor (1.0, 0.5) pos (0.99, 0.86) zoom 0.25 action actions add "images/interface/[interface_resolution]/Player_menu/inventory_filters.webp" zoom interface_adjustment for f, filter in enumerate(["gift", "key"]): use inventory_filter( [SetLocalVariable("inventory_Item", None), SetLocalVariable("inventory_filter", filter), SetLocalVariable("inventory_page", 0)], filter_type = filter, pos = (0.451 + f*0.097, 0.205), xysize = (int(372*game_resolution), int(124*game_resolution)), selected = inventory_filter == filter) text "ITEM NAME{alpha=0.0}_{/alpha}" anchor (0.0, 0.5) pos (0.673, 0.234): size 35 if inventory_Item: if isinstance(inventory_Item, ClothingClass): text "[inventory_Item.name!u]" anchor (1.0, 0.5) pos (0.925, 0.234): if len(inventory_Item.name) > 20: size 25 elif len(inventory_Item.name) > 15: size 30 else: size 35 elif isinstance(inventory_Item, ItemClass): text "[inventory_Item.name!u]" anchor (1.0, 0.5) pos (0.925, 0.234): if len(inventory_Item.name) > 20: size 25 elif len(inventory_Item.name) > 15: size 30 else: size 35 text "[inventory_Item.description]" anchor (0.5, 0.0) pos (0.8, 0.35) xysize (0.25, 0.44): size 40 if inventory_Item.filter_type == "key_gifts" and inventory_Item.Owner == Player: vbox anchor (0.5, 0.5) pos (0.8, 0.77): spacing 5 text "ACTIVE?": size 40 use options_onoff( ToggleField(inventory_Item, "active"), selected = inventory_Item.active) text "CASH{alpha=0.0}_{/alpha}" anchor (0.0, 0.5) pos (0.673, 0.905): size 45 text "$['{:,}'.format(Player.cash)]" anchor (1.0, 0.5) pos (0.9265, 0.905): size 45 # phone.rpy: Celcius-Fahrenheit toggle for player phone screen home_screen(): style_prefix "phone" if time_index in {1, 2, 3}: add "images/interface/[interface_resolution]/phone/clock_[time_index].webp" zoom high_resolution_interface_adjustment elif time_index < 1: add "images/interface/[interface_resolution]/phone/clock_1.webp" zoom high_resolution_interface_adjustment elif time_index > 3: add "images/interface/[interface_resolution]/phone/clock_3.webp" zoom high_resolution_interface_adjustment if weather: add "images/interface/[interface_resolution]/phone/weather_[weather].webp" zoom high_resolution_interface_adjustment else: add "images/interface/[interface_resolution]/phone/weather.webp" zoom high_resolution_interface_adjustment text "[week[weekday]], [time_options[time_index]]" anchor (0.0, 0.5) pos (0.15, 0.132): size 30 color "#ffffff" # Celcius-Fahrenheit toggle key "d" action ToggleVariable("persistent.Fahrenheit") if persistent.Fahrenheit: text u"['{:.1f}'.format(temperature[time_index]*9/5+32)] \u00b0F" anchor (0.0, 0.5) pos (0.22, 0.169): size 30 color "#ffffff" else: text u"[temperature[time_index]] \u00b0C" anchor (0.0, 0.5) pos (0.22, 0.169): size 30 color "#ffffff" button: background At(f"images/interface/{interface_resolution}/phone/search_bar_background.webp", interface_zoom) idle_foreground At(f"images/interface/{interface_resolution}/phone/search_bar_idle.webp", high_resolution_interface_zoom) hover_foreground At(f"images/interface/{interface_resolution}/phone/search_bar.webp", high_resolution_interface_zoom) selected_idle_foreground At(f"images/interface/{interface_resolution}/phone/search_bar.webp", high_resolution_interface_zoom) selected input_cheats action [ SetScreenVariable("current_input", ""), ToggleVariable("input_cheats")] focus_mask True add "images/interface/[interface_resolution]/phone/search_bar_microphone.webp" zoom high_resolution_interface_adjustment add "images/interface/[interface_resolution]/phone/search_bar_icon.webp" zoom high_resolution_interface_adjustment if input_cheats: input value ScreenVariableInputValue("current_input", default = True) anchor (0.0, 0.5) pos (0.224, 0.235): font "agency_fb.ttf" size 30 color "#ffffff" length 25 key "K_RETURN" action [ SetVariable("input_cheats", False), Function(enter_cheat_code, current_input)] if humhum_available and not humhum_hidden: $ humhumthread_to_display = HumHumPool.HumHumThreads[list(HumHumPool.HumHumThreads.keys())[humhum_index]] add "images/interface/[interface_resolution]/phone/home_humhum_box.webp" zoom interface_adjustment add "images/interface/[interface_resolution]/phone/home_humhum_newest.webp" zoom high_resolution_interface_adjustment imagebutton: idle At(f"images/interface/{interface_resolution}/phone/home_humhum_left_idle.webp", high_resolution_interface_zoom) hover At(f"images/interface/{interface_resolution}/phone/home_humhum_left.webp", high_resolution_interface_zoom) action [ SetVariable("humhum_index", (humhum_index - 1) % len(list(HumHumPool.HumHumThreads.keys()))), SetVariable("humhum_yadjustment.value", 0), SetVariable("humhum_reply_yadjustment.value", 0)] imagebutton: idle At(f"images/interface/{interface_resolution}/phone/home_humhum_right_idle.webp", high_resolution_interface_zoom) hover At(f"images/interface/{interface_resolution}/phone/home_humhum_right.webp", high_resolution_interface_zoom) action [ SetVariable("humhum_index", (humhum_index + 1) % len(list(HumHumPool.HumHumThreads.keys()))), SetVariable("humhum_yadjustment.value", 0), SetVariable("humhum_reply_yadjustment.value", 0)] if len(humhumthread_to_display.HumHums) > 1: imagebutton: idle At(f"images/interface/{interface_resolution}/phone/home_humhum_comments_idle.webp", interface_zoom) hover At(f"images/interface/{interface_resolution}/phone/home_humhum_comments.webp", interface_zoom) action ToggleVariable("humhum_expanded") else: add "images/interface/[interface_resolution]/phone/home_humhum_comments_idle.webp" zoom interface_adjustment text "COMMENTS" anchor (0.5, 0.5) pos (0.5, 0.458): font "agency_fb_bold.ttf" size 24 color "#4e4e4e" if humhumthread_to_display.HumHums[0].Owner != Player: add "images/interface/full/icons/[humhumthread_to_display.HumHums[0].Owner.tag].webp" anchor (0.5, 0.5) pos (0.18, 0.350) zoom 0.18 else: add "images/interface/full/icons/Player_[Player.background_color].webp" anchor (0.5, 0.5) pos (0.18, 0.350) zoom 0.18 fixed anchor (0.0, 0.0) pos (0.238, 0.325) xysize (0.6, 0.102): viewport id "home_humhum_viewport" yadjustment humhum_yadjustment anchor (0.0, 0.0) pos (0.02, 0.01) xysize (0.96, 0.98): draggable True mousewheel True text "[humhumthread_to_display.HumHums[0].body!i]" align (0.0, 0.0): size 28 text_align 0.0 vbar value YScrollValue("home_humhum_viewport") anchor (0.5, 0.5) pos (0.855, 0.377) xysize (int(27*game_resolution), int(227*game_resolution)): base_bar Frame("images/interface/full/phone/home_humhum_scrollbar.webp") thumb "images/interface/full/phone/home_humhum_scrollbar_thumb.webp" thumb_offset int(66*game_resolution/2/3) unscrollable "hide" if humhum_expanded and len(humhumthread_to_display.HumHums) > 1: add "images/interface/[interface_resolution]/phone/home_humhum_reply_box.webp" zoom interface_adjustment fixed anchor (0.5, 0.0) pos (0.5, 0.487) xysize (0.73, 0.172): viewport id "home_humhum_reply_viewport" yadjustment humhum_reply_yadjustment anchor (0.0, 0.0) pos (0.02, 0.01) xysize (0.96, 0.98): draggable True mousewheel True vbox xsize 1.0: null height 4 for h in range(1, len(humhumthread_to_display.HumHums)): hbox xalign 0.0 xsize 0.98: vbox align (0.0, 0.5) xsize int(252*0.18): if humhumthread_to_display.HumHums[h].Owner != Player: add "images/interface/full/icons/[humhumthread_to_display.HumHums[h].Owner.tag].webp" yalign 0.0 zoom 0.18 else: add "images/interface/full/icons/Player_[Player.background_color].webp" yalign 0.0 zoom 0.18 # text "[humhumthread_to_display.HumHums[h].Owner.call_sign]": # size 24 null width 8 frame align (0.0, 0.5) xsize int(770*game_resolution): background Frame("images/interface/full/phone/home_humhum_comments_frame.webp") text "[humhumthread_to_display.HumHums[h].body!i]" align (0.0, 0.0): size 28 text_align 0.0 null height 4 vbar value YScrollValue("home_humhum_reply_viewport") anchor (0.5, 0.0) pos (0.855, 0.490) xysize (int(27*game_resolution), int(348*game_resolution)): base_bar Frame("images/interface/full/phone/home_humhum_reply_scrollbar.webp") thumb "images/interface/full/phone/home_humhum_scrollbar_thumb.webp" thumb_offset int(66*game_resolution/2/3) unscrollable "hide" # if len(humhumthread_to_display.HumHums) > 1: # imagebutton: # idle At(f"images/interface/{interface_resolution}/phone/home_humhum_reply_idle.webp", interface_zoom) # hover At(f"images/interface/{interface_resolution}/phone/home_humhum_reply.webp", interface_zoom) # action ToggleVariable("humhum_expanded") # else: add "images/interface/[interface_resolution]/phone/home_humhum_reply_idle.webp" zoom interface_adjustment text "Share your hums. . ." anchor (0.0, 0.5) pos (0.149, 0.682): size 22 color "#4e4e4e" text "REPLY" anchor (0.5, 0.5) pos (0.802, 0.682): font "agency_fb_bold.ttf" size 24 color "#4e4e4e" imagebutton anchor (0.5, 0.5) pos (0.75, 0.8): idle At("images/interface/full/icons/blah_idle.webp", phone_icon) hover At("images/interface/full/icons/blah.webp", phone_icon) action [ SetScreenVariable("loading", True), SetVariable("current_phone_screen", "blah_choice")] # Player_menu.rpy: adds friendship points to portraits screen relationships_screen(): default relationships_filter = None default relationships_Entry = None add "images/interface/[interface_resolution]/Player_menu/relationships_label.webp" zoom interface_adjustment if interface_blinking: text "RELATIONSHIPS{alpha=0.0}_{/alpha}" anchor (0.0, 0.5) pos (0.064, 0.234): size 35 else: text "RELATIONSHIPS_" anchor (0.0, 0.5) pos (0.064, 0.234): size 35 add "images/interface/[interface_resolution]/Player_menu/relationships_side.webp" zoom interface_adjustment text "FILTER" anchor (0.0, 0.5) pos (0.064, 0.331): size 35 for f, filter in enumerate(["friend", "companion"]): if relationships_filter == filter: $ actions = SetLocalVariable("relationships_filter", None) else: $ actions = [ SetLocalVariable("relationships_Entry", None), SetLocalVariable("relationships_filter", filter)] if filter == "friend": $ size = 30 elif filter == "companion": $ size = 24 use relationships_filter( actions, filter_type = filter, pos = (0.207 + f*0.058, 0.317), xysize = (int(210*game_resolution), int(60*game_resolution)), text_size = size, selected = relationships_filter == filter) vpgrid id "relationships_viewport" anchor (0.5, 0.0) pos (0.18, 0.392) xysize (int(911*game_resolution), int(1114*game_resolution)): cols 1 draggable True mousewheel True for C in GameState.all_Characters: if C in GameState.all_Companions: if relationships_filter not in {"companion", None}: continue if C not in GameState.active_Companions(): continue $ kind = "companion" else: if relationships_filter not in {"friend", None}: continue ## eventually remove continue $ kind = "friend" button xysize (int(911*game_resolution), int(191*game_resolution)): idle_background At(f"images/interface/{interface_resolution}/Player_menu/relationships_{kind}_idle.webp", high_resolution_interface_zoom) hover_background At(f"images/interface/{interface_resolution}/Player_menu/relationships_{kind}.webp", high_resolution_interface_zoom) selected_idle_background At(f"images/interface/{interface_resolution}/Player_menu/relationships_{kind}.webp", high_resolution_interface_zoom) selected relationships_Entry == C if C.full_name == "???": text "[C.name]" anchor (0.0, 0.5) pos (0.1, 0.5): font "agency_fb.ttf" size 36 color "#000000" else: text "[C.full_name]" anchor (0.0, 0.5) pos (0.1, 0.5): font "agency_fb.ttf" size 36 color "#000000" action SetLocalVariable("relationships_Entry", C) vbar value YScrollValue("relationships_viewport") anchor (0.5, 0.0) pos (0.315, 0.392) xysize (int(40*game_resolution), int(1114*game_resolution)): base_bar Frame("images/interface/full/Player_menu/scrollbar.webp") thumb "images/interface/full/Player_menu/scrollbar_thumb.webp" thumb_offset int(276*game_resolution/2/10) unscrollable "hide" if relationships_Entry: add "images/interface/[interface_resolution]/Player_menu/relationships_box.webp" zoom interface_adjustment add "images/interface/[interface_resolution]/Player_menu/relationships_bottom.webp" zoom interface_adjustment add "images/interface/full/photos/[relationships_Entry.tag].webp" anchor (0.5, 0.5) pos (0.4215, 0.3785) zoom 0.5 add "images/interface/[interface_resolution]/Player_menu/relationships_love.webp" zoom interface_adjustment text "[relationships_Entry.love]" anchor (0.5, 0.5) pos (0.435, 0.4655): font "agency_fb.ttf" size 30 color "#000000" add "images/interface/[interface_resolution]/Player_menu/relationships_trust.webp" zoom interface_adjustment text "[relationships_Entry.trust]" anchor (0.5, 0.5) pos (0.435, 0.5065): font "agency_fb.ttf" size 30 color "#000000" text "PUBLIC NAME" anchor (0.0, 0.5) pos (0.495, 0.242): font "agency_fb.ttf" size 28 text "[relationships_Entry.public_name]" anchor (1.0, 0.5) pos (0.713, 0.242): font "agency_fb.ttf" size 28 text "RELATIONSHIP STATUS" anchor (0.0, 0.5) pos (0.495, 0.297): font "agency_fb.ttf" size 28 if relationships_Entry not in Partners: text "Single" anchor (1.0, 0.5) pos (0.713, 0.297): font "agency_fb.ttf" size 28 elif relationships_Entry.check_traits("polyamorous"): text "Polyamorous" anchor (1.0, 0.5) pos (0.713, 0.297): font "agency_fb.ttf" size 28 else: text "In a relationship" anchor (1.0, 0.5) pos (0.713, 0.297): font "agency_fb.ttf" size 28 text "HER PETNAME" anchor (0.0, 0.5) pos (0.495, 0.353): font "agency_fb.ttf" size 28 text "[relationships_Entry.petname]" anchor (1.0, 0.5) pos (0.713, 0.353): font "agency_fb.ttf" size 28 text "MY PETNAME" anchor (0.0, 0.5) pos (0.495, 0.411): font "agency_fb.ttf" size 28 text "[relationships_Entry.Player_petname]" anchor (1.0, 0.5) pos (0.713, 0.411): font "agency_fb.ttf" size 28 text "MOOD" anchor (0.5, 0.5) pos (0.829, 0.234): font "agency_fb.ttf" size 28 hbox anchor (0.0, 0.5) pos (0.736, 0.286) ysize int(107*game_resolution): if relationships_Entry.is_in_normal_mood(): use relationships_status( "happy", text_color = "#00ff06") if relationships_Entry.get_status() == "mad": use relationships_status( "mad", text_color = "#f00d48") if relationships_Entry.status["horny"] or relationships_Entry.status["nympho"]: use relationships_status( "horny", text_color = "#dd64e8") for status, color in (("sad", "#0dd3f0"), ("heartbroken", "#ffd304")): if relationships_Entry.status.get(status, False): use relationships_status( status, text_color = color) text "FRIENDSHIPS" anchor (0.5, 0.55) pos (0.829, 0.3455): font "agency_fb.ttf" size 22 text "Best Friends" anchor (0.5, 0.55) pos (0.771, 0.387): font "agency_fb.ttf" size 20 text "Good Friends" anchor (0.5, 0.55) pos (0.834, 0.387): font "agency_fb.ttf" size 20 text "Friends" anchor (0.5, 0.55) pos (0.896, 0.387): font "agency_fb.ttf" size 20 text "Acquaintances" anchor (0.5, 0.55) pos (0.771, 0.416): font "agency_fb.ttf" size 18 text "Rivals" anchor (0.5, 0.55) pos (0.834, 0.416): font "agency_fb.ttf" size 20 text "Enemies" anchor (0.5, 0.55) pos (0.896, 0.416): font "agency_fb.ttf" size 20 $ friendship_dict = relationships_Entry.friendship_thresholds vpgrid id "relationships_friendship_viewport" anchor (0.0, 0.5) pos (0.505, 0.4935) xysize (0.385, int(195*game_resolution)): cols len(friendship_dict) draggable True mousewheel True spacing 20 for C in friendship_dict: if C != relationships_Entry.tag and getattr(store, C) in GameState.active_Companions(): $ friendship = relationships_Entry.get_friendship(getattr(store, C)) fixed xysize (int(135*game_resolution), int(195*game_resolution)): add "images/interface/full/photos/[C].webp" align (0.5, 0.5) zoom 0.13 add "images/interface/[interface_resolution]/Player_menu/relationships_[friendship].webp" align (0.5, 0.5) zoom interface_adjustment if not persistent.fps_portraits: text "[relationships_Entry.friendship[C]]" align (0.51, 0.98) size 16 outlines [(1,"#000")]: if friendship == 3: color "#01FF60" elif friendship == 2: color "#01FED2" elif friendship == 1: color "#00A1FB" elif friendship == -1: color "#F55209" elif friendship == -2: color "#F60D4A" for q, quirk in enumerate(relationships_Entry.database["quirks"]): if " 2 - " in quirk and q == 0: $ q = 1 text "[quirk]" anchor (0.0, 0.5) pos (0.37 + 0.288*q, 0.5815): font "agency_fb.ttf" size 30 frame anchor (0.5, 0.0) pos (0.503 + 0.288*q, 0.623) xsize 0.275: text "[relationships_Entry.database['quirks'][quirk]]" xalign 0.0: font "agency_fb.ttf" size 28 text_align 0.0 # updates.rpy: shorter notification timer screen updates_screen(): default update_message = None style_prefix "updates" if update_message: timer 2.8 action SetLocalVariable("update_message", None) # timer 3.3 frame: if renpy.get_screen("sex_screen"): anchor (0.0, 0.0) pos (0.07, 0.0125) # (0.0, 1.0) pos (0.02, 0.98) else: anchor (0.0, 0.0) pos (0.02, 0.0125) # (0.0, 0.0) pos (0.02, 0.02) text "[update_message]" at transform: # better always adjust the sum of these timer values to the "timer" one above fade_in(0.4) # 0.4 pause 2.0 # 2.5 fade_out(0.4) # 0.4 elif update_messages: instant action [ SetLocalVariable("update_message", update_messages[0]), RemoveFromSet(update_messages, update_messages[0])] # game_menu.rpy: hotkeys added to the Options menu screen options(): default tab = "graphics" default tab_label = "GRAPHIC OPTIONS" default image_filters = [None, "comic", "tv"] default image_caches = [512, 1024, 2048, 4096] default default_body_hairs = ["default", "hairy", "shaven"] layer "screens" tag menu modal True style_prefix "game_menu" if persistent.animated_interface: timer 1.0 action ToggleVariable("interface_blinking") repeat True modal True use menu_background(spinning = True) add "images/interface/[interface_resolution]/options/frame.webp" zoom interface_adjustment add "images/interface/[interface_resolution]/options/buttons.webp" zoom interface_adjustment add "images/interface/[interface_resolution]/options/label.webp" zoom interface_adjustment use options_section( [SetScreenVariable("tab", "graphics"), SetScreenVariable("tab_label", "GRAPHICS OPTIONS")], pos = (0.208, 0.204), xysize = (int(372*game_resolution), int(124*game_resolution)), text = "GRAPHICS", selected = tab == "graphics") use options_section( [SetScreenVariable("tab", "audio"), SetScreenVariable("tab_label", "AUDIO OPTIONS")], pos = (0.305, 0.204), xysize = (int(372*game_resolution), int(124*game_resolution)), text = "AUDIO", selected = tab == "audio") use options_section( [SetScreenVariable("tab", "hotkeys"), SetScreenVariable("tab_label", "HOTKEYS")], pos = (0.402, 0.204), xysize = (int(372*game_resolution), int(124*game_resolution)), text = "HOTKEYS", selected = tab == "hotkeys") use options_section( [SetScreenVariable("tab", "gameplay"), SetScreenVariable("tab_label", "GAMEPLAY OPTIONS")], pos = (0.499, 0.204), xysize = (int(372*game_resolution), int(124*game_resolution)), text = "GAMEPLAY", selected = tab == "gameplay") # new mod options tab use base_button( [SetScreenVariable("tab", "mod"), SetScreenVariable("tab_label", "MOD OPTIONS")], pos = (0.610, 0.198), xysize = (int(395*game_resolution), int(153*game_resolution)), text = "TNHUXMod", selected = tab == "mod", text_size = 29) # new summoner mod options tab if renpy.loadable("pepplez_summoner.rpy"): use base_button( [SetScreenVariable("tab", "summoner"), SetScreenVariable("tab_label", "MOD OPTIONS")], pos = (0.713, 0.198), xysize = (int(395*game_resolution), int(153*game_resolution)), text = "Summoner", selected = tab == "summoner", text_size = 29) if interface_blinking: text "[tab_label]{alpha=0.0}_{/alpha}" anchor (0.0, 0.5) pos (0.065, 0.232) else: text "[tab_label]_" anchor (0.0, 0.5) pos (0.065, 0.232) viewport id "options_viewport" anchor (0.5, 0.0) pos (0.4235, 0.31) xysize (0.72, 0.62): draggable True mousewheel True vbox align (0.5, 0.0): spacing 0 if tab == "graphics": hbox: fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "WINDOWED MODE" anchor (0.0, 0.5) pos (0.035, 0.235) text "Toggle between windowed and fullscreen modes" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 if preferences.fullscreen: use options_onoff( Preference("display", "window"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = not preferences.fullscreen, button_shadow = True) else: use options_onoff( Preference("display", "fullscreen"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = not preferences.fullscreen, button_shadow = True) fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "FLASHING EFFECTS" anchor (0.0, 0.5) pos (0.035, 0.235) text "Enable flashing lights and effects during gameplay" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.flashing_lights"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.flashing_lights, button_shadow = True) hbox: fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "CINEMATIC BARS" anchor (0.0, 0.5) pos (0.035, 0.235) text "Enable cinematic bars during events" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.cinematic_bars"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.cinematic_bars, button_shadow = True) fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "LOW RESOLUTION (REQUIRES RESTART)" anchor (0.0, 0.5) pos (0.035, 0.235) text "Use downscaled images - may reduce crashing on devices with low available memory" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.low_res"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.low_res, button_shadow = True) hbox: fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "IMAGE FILTER" anchor (0.0, 0.5) pos (0.035, 0.235) text "Toggle between filter overlays" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.45: font "agency_fb.ttf" size 24 text_align 0.0 use customization_button( SetVariable("persistent.image_filter", image_filters[(image_filters.index(persistent.image_filter) - 1) % len(image_filters)]), anchor = (0.0, 1.0), pos = (0.5, 0.9), xysize = (int(197*game_resolution), int(181*game_resolution)), image = "images/interface/[interface_resolution]/customization/left.webp", image_zoom = high_resolution_interface_adjustment, image_shadow = True) if persistent.image_filter: text "[persistent.image_filter!u]" anchor (0.5, 1.0) pos (0.73, 0.74) else: text "OFF" anchor (0.5, 1.0) pos (0.73, 0.74) use customization_button( SetVariable("persistent.image_filter", image_filters[(image_filters.index(persistent.image_filter) + 1) % len(image_filters)]), anchor = (1.0, 1.0), pos = (0.96, 0.9), xysize = (int(197*game_resolution), int(181*game_resolution)), image = "images/interface/[interface_resolution]/customization/right.webp", image_zoom = high_resolution_interface_adjustment, image_shadow = True) fixed xysize (int(684*2.0*game_resolution), int(175*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "LIVE2D LITE" anchor (0.0, 0.5) pos (0.035, 0.235) text "Disable Live2D features that may negatively impact game performance, including physics and breathing animations" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.live2d_lite"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.live2d_lite, button_shadow = True) hbox: fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "PATREON SILHOUETTES" anchor (0.0, 0.5) pos (0.035, 0.235) text "Enable background silhouettes belonging to Patreon supporters" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.silhouettes_enabled"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.silhouettes_enabled, button_shadow = True) fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "SHOW BACKGROUND" anchor (0.0, 0.5) pos (0.035, 0.235) text "Enable characters to be displayed in the background" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.show_background"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.show_background, button_shadow = True) hbox: fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "HOVER EFFECT" anchor (0.0, 0.5) pos (0.035, 0.235) text "Highlight interactable characters upon mouse over" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.hover_highlights"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.hover_highlights, button_shadow = True) fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "MAP ICONS" anchor (0.0, 0.5) pos (0.035, 0.235) text "Display character icons on the map" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.map_icons"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.map_icons, button_shadow = True) hbox: fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "TOGGLE UI" anchor (0.0, 0.5) pos (0.035, 0.235) text "Toggle visibility of UI" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 if belt_hidden or sex_screen_hidden: use options_onoff( [SetVariable("belt_hidden", False), SetVariable("sex_screen_hidden", False)], anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = (not belt_hidden and not sex_screen_hidden), button_shadow = True) else: use options_onoff( [SetVariable("belt_hidden", True), SetVariable("sex_screen_hidden", True)], anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = (not belt_hidden and not sex_screen_hidden), button_shadow = True) fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "ANIMATED INTERFACE" anchor (0.0, 0.5) pos (0.035, 0.235) text "Enable animations in interfaces. Disable interface filters under TNHUXMod" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.animated_interface"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.animated_interface, button_shadow = True) hbox: fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "LARGE TEXT MODE" anchor (0.0, 0.5) pos (0.035, 0.235) text "Increase text size in dialogue and choice menus" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.large_text_mode"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.large_text_mode, button_shadow = True) fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "BLOOD/GORE ENABLED" anchor (0.0, 0.5) pos (0.035, 0.235) text "Enable blood and (very light) gore" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.gore_enabled"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.gore_enabled, button_shadow = True) hbox: fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "IMAGE CACHE SIZE (REQUIRES RESTART)" anchor (0.0, 0.5) pos (0.035, 0.235) use customization_button( SetVariable("persistent.image_cache", image_caches[(image_caches.index(persistent.image_cache) - 1) % len(image_caches)]), anchor = (0.0, 1.0), pos = (0.25, 0.9), xysize = (int(197*game_resolution), int(181*game_resolution)), image = "images/interface/[interface_resolution]/customization/left.webp", image_zoom = high_resolution_interface_adjustment, image_shadow = True) text "[persistent.image_cache] MB" anchor (0.5, 1.0) pos (0.5, 0.74) use customization_button( SetVariable("persistent.image_cache", image_caches[(image_caches.index(persistent.image_cache) + 1) % len(image_caches)]), anchor = (1.0, 1.0), pos = (0.75, 0.9), xysize = (int(197*game_resolution), int(181*game_resolution)), image = "images/interface/[interface_resolution]/customization/right.webp", image_zoom = high_resolution_interface_adjustment, image_shadow = True) fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "PRELOAD ASSETS (REQUIRES RESTART)" anchor (0.0, 0.5) pos (0.035, 0.235) hbox anchor (0.5, 1.0) pos (0.5, 0.86): spacing 10 for asset in ("characters", "backgrounds", "interfaces"): use base_button( ToggleSetMembership(persistent.preloads, asset), xysize = (int(350*game_resolution), int(150*game_resolution)), selected = asset in persistent.preloads, text = asset.upper(), text_size = 28, animated = False) hbox: fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "WAIT FOR IMAGE PREDICTION" anchor (0.0, 0.5) pos (0.035, 0.235) text "Pause at loading screen until image prediction is complete.\nTurn this off to vastely speed-up loading times!" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.wait_for_prediction"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.wait_for_prediction, button_shadow = True) fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "IMAGE CACHE USAGE" anchor (0.0, 0.5) pos (0.035, 0.235) bar value renpy.display.im.cache.get_current_size(2)/renpy.display.im.cache.cache_limit range 1.0 anchor (0.5, 0.0) pos (0.492, 0.58) xysize (int(600*2.0*game_resolution), int(20*2.0*game_resolution)): left_bar Frame(At("images/interface/full/options/scrollbar.webp", tint("#bb1616"))) right_bar Frame("images/interface/full/options/scrollbar.webp") thumb None hbox: fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "ALLOW MULTITHREADING" anchor (0.0, 0.5) pos (0.035, 0.235) text "Allow multithreaded Live2D updates - disabling may improve performance on older CPUs" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.multithreading"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.multithreading, button_shadow = True) null width int(684*2.0*game_resolution) elif tab == "audio": hbox: fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "EFFECTS VOLUME" anchor (0.0, 0.5) pos (0.035, 0.235) bar value Preference("sound volume") anchor (0.5, 0.0) pos (0.492, 0.58) xysize (int(600*2.0*game_resolution), int(20*2.0*game_resolution)): base_bar Frame("images/interface/full/options/scrollbar.webp") thumb "images/interface/full/options/scrollbar_thumb.webp" thumb_offset int(7*2.0*game_resolution) fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "MUTE" anchor (0.0, 0.5) pos (0.035, 0.235) text "Disable all in-game sound" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 if persistent.volume_muted: use options_onoff( [SetVariable("persistent.volume_muted", False), SetMute(["sfx", "music"], False)], anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.volume_muted, button_shadow = True) else: use options_onoff( [SetVariable("persistent.volume_muted", True), SetMute(["sfx", "music"], True)], anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.volume_muted, button_shadow = True) hbox: fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "MUSIC VOLUME" anchor (0.0, 0.5) pos (0.035, 0.235) bar value Preference("music volume") anchor (0.5, 0.0) pos (0.492, 0.58) xysize (int(600*2.0*game_resolution), int(20*2.0*game_resolution)): base_bar Frame("images/interface/full/options/scrollbar.webp") thumb "images/interface/full/options/scrollbar_thumb.webp" thumb_offset int(7*2.0*game_resolution) null width int(684*2.0*game_resolution) elif tab == "hotkeys": grid 4 6 pos (0.01, 0.02): # grid 4 4 xspacing 17 # 85 yspacing 39 # 110 hbox xalign 0.0: fixed xysize (int(158*game_resolution), int(150*game_resolution)): add "images/interface/[interface_resolution]/options/key.webp" zoom interface_adjustment text "1": size 36 color "#000000" text "QUIKLOC 1" align (0.0, 0.5) hbox xalign 0.0: fixed xysize (int(158*game_resolution), int(150*game_resolution)): add "images/interface/[interface_resolution]/options/key.webp" zoom interface_adjustment text "2": size 36 color "#000000" text "QUIKLOC 2" align (0.0, 0.5) hbox xalign 0.0: fixed xysize (int(158*game_resolution), int(150*game_resolution)): add "images/interface/[interface_resolution]/options/key.webp" zoom interface_adjustment text "3": size 36 color "#000000" text "QUIKLOC 3" align (0.0, 0.5) hbox xalign 0.0: fixed xysize (int(158*game_resolution), int(150*game_resolution)): add "images/interface/[interface_resolution]/options/key.webp" zoom interface_adjustment text "-": size 36 color "#000000" text "TOGGLE MUTE" align (0.0, 0.5) hbox xalign 0.0: fixed xysize (int(158*game_resolution), int(150*game_resolution)): add "images/interface/[interface_resolution]/options/key.webp" zoom interface_adjustment text "Q": size 36 color "#000000" text "SKIP DAY" align (0.0, 0.5) hbox xalign 0.0: fixed xysize (int(158*game_resolution), int(150*game_resolution)): add "images/interface/[interface_resolution]/options/key.webp" zoom interface_adjustment text "W": size 36 color "#000000" text "TOGGLE QUICK MENU" align (0.0, 0.5) hbox xalign 0.0: fixed xysize (int(158*game_resolution), int(150*game_resolution)): add "images/interface/[interface_resolution]/options/key.webp" zoom interface_adjustment text "R": size 36 color "#000000" text "PLAYER ROOM" align (0.0, 0.5) hbox xalign 0.0: fixed xysize (int(158*game_resolution), int(150*game_resolution)): add "images/interface/[interface_resolution]/options/key.webp" zoom interface_adjustment text "T": size 36 color "#000000" text "REMOTE VIBRATOR" align (0.0, 0.5) # if not Player.Inventory.get("remote_vibrator_controller"): # at Transform(alpha = 0.0) hbox xalign 0.0: fixed xysize (int(158*game_resolution), int(150*game_resolution)): add "images/interface/[interface_resolution]/options/key.webp" zoom interface_adjustment text "I": size 36 color "#000000" text "INVENTORY" align (0.0, 0.5) hbox xalign 0.0: fixed xysize (int(158*game_resolution), int(150*game_resolution)): add "images/interface/[interface_resolution]/options/key.webp" zoom interface_adjustment text "O": size 36 color "#000000" text "POOL" align (0.0, 0.5) hbox xalign 0.0: fixed xysize (int(158*game_resolution), int(150*game_resolution)): add "images/interface/[interface_resolution]/options/key.webp" zoom interface_adjustment text "P": size 36 color "#000000" text "PHONE" align (0.0, 0.5) hbox xalign 0.0: fixed xysize (int(158*game_resolution), int(150*game_resolution)): add "images/interface/[interface_resolution]/options/key.webp" zoom interface_adjustment text "A": size 36 color "#000000" text "TOGGLE AUTO-FORWARD" align (0.0, 0.5) hbox xalign 0.0: fixed xysize (int(158*game_resolution), int(150*game_resolution)): add "images/interface/[interface_resolution]/options/key.webp" zoom interface_adjustment text "S": size 36 color "#000000" text "SCREENSHOT" align (0.0, 0.5) hbox xalign 0.0: fixed xysize (int(158*game_resolution), int(150*game_resolution)): add "images/interface/[interface_resolution]/options/key.webp" zoom interface_adjustment text "D": size 36 color "#000000" text "TOGGLE TEMPERATURE" align (0.0, 0.5) hbox xalign 0.0: fixed xysize (int(158*game_resolution), int(150*game_resolution)): add "images/interface/[interface_resolution]/options/key.webp" zoom interface_adjustment text "F": size 36 color "#000000" text "TOGGLE FULLSCREEN" align (0.0, 0.5) hbox xalign 0.0: fixed xysize (int(158*game_resolution), int(150*game_resolution)): add "images/interface/[interface_resolution]/options/key.webp" zoom interface_adjustment text "G": size 36 color "#000000" text "DANGER ROOM" align (0.0, 0.5) hbox xalign 0.0: fixed xysize (int(158*game_resolution), int(150*game_resolution)): add "images/interface/[interface_resolution]/options/key.webp" zoom interface_adjustment text "H": size 36 color "#000000" text "TOGGLE UI" align (0.0, 0.5) hbox xalign 0.0: fixed xysize (int(158*game_resolution), int(150*game_resolution)): add "images/interface/[interface_resolution]/options/key.webp" zoom interface_adjustment text "J": size 36 color "#000000" text "JOURNAL" align (0.0, 0.5) hbox xalign 0.0: fixed xysize (int(158*game_resolution), int(150*game_resolution)): add "images/interface/[interface_resolution]/options/key.webp" zoom interface_adjustment text "K": size 36 color "#000000" text "KITCHEN" align (0.0, 0.5) hbox xalign 0.0: fixed xysize (int(158*game_resolution), int(150*game_resolution)): add "images/interface/[interface_resolution]/options/key.webp" zoom interface_adjustment text "L": size 36 color "#000000" text "MALL" align (0.0, 0.5) hbox xalign 0.0: fixed xysize (int(158*game_resolution), int(150*game_resolution)): add "images/interface/[interface_resolution]/options/key.webp" zoom interface_adjustment text "X": size 36 color "#000000" text "XAVIER'S STUDY" align (0.0, 0.5) hbox xalign 0.0: fixed xysize (int(158*game_resolution), int(150*game_resolution)): add "images/interface/[interface_resolution]/options/key.webp" zoom interface_adjustment text "C": size 36 color "#000000" text "CLASSROOM" align (0.0, 0.5) hbox xalign 0.0: fixed xysize (int(158*game_resolution), int(150*game_resolution)): add "images/interface/[interface_resolution]/options/key.webp" zoom interface_adjustment text "V": size 36 color "#000000" text "TOGGLE SELF-VOICING" align (0.0, 0.5) hbox xalign 0.0: fixed xysize (int(158*game_resolution), int(150*game_resolution)): add "images/interface/[interface_resolution]/options/key.webp" zoom interface_adjustment text "M": size 36 color "#000000" text "MAP" align (0.0, 0.5) elif tab == "gameplay": hbox: fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "SKIP UNSEEN TEXT" anchor (0.0, 0.5) pos (0.035, 0.235) text "Enable skipping through dialogue and narrations that have not been seen" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("preferences.skip_unseen"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = preferences.skip_unseen, button_shadow = True) if config.rollback_enabled: fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "SCROLLING ROLLBACK" anchor (0.0, 0.5) pos (0.035, 0.235) text "Rollback by scrolling the mousewheel" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 if persistent.scrolling_rollback: use options_onoff( [Function(config.keymap["rollback"].remove, "mousedown_4"), Function(config.keymap["rollforward"].remove, "mousedown_5"), SetVariable("persistent.scrolling_rollback", False), Function(renpy.clear_keymap_cache)], anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.scrolling_rollback, button_shadow = True) else: use options_onoff( [Function(config.keymap["rollback"].append, "mousedown_4"), Function(config.keymap["rollforward"].append, "mousedown_5"), SetVariable("persistent.scrolling_rollback", True), Function(renpy.clear_keymap_cache)], anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.scrolling_rollback, button_shadow = True) hbox: fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "TOOLTIPS" anchor (0.0, 0.5) pos (0.035, 0.235) text "Enable tooltips, revealed by hovering over an element" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.tooltips_enabled"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.tooltips_enabled, button_shadow = True) fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "JOURNAL HINTS" anchor (0.0, 0.5) pos (0.035, 0.235) text "Enable objective hints in the journal, revealed by hovering over an objective" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.journal_hints"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.journal_hints, button_shadow = True) hbox: fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "WARDROBE DIALOGUE" anchor (0.0, 0.5) pos (0.035, 0.235) text "Enable dialogue and character reactions in the wardrobe menu" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.Wardrobe_dialogue"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.Wardrobe_dialogue, button_shadow = True) fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "WARDROBE MOVEMENT" anchor (0.0, 0.5) pos (0.035, 0.235) text "Enable dynamic movement of the wardrobe menu camera" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.Wardrobe_movement"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.Wardrobe_movement, button_shadow = True) hbox: fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "PLAYER BODY VISIBLE" anchor (0.0, 0.5) pos (0.035, 0.235) text "Show Player's body during sex" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 if Player.check_traits("body_visible"): use options_onoff( Function(Player.remove_trait, "body_visible"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = Player.check_traits("body_visible"), button_shadow = True) else: use options_onoff( Function(Player.give_trait, "body_visible"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = Player.check_traits("body_visible"), button_shadow = True) fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "PLAYER HEAD VISIBLE" anchor (0.0, 0.5) pos (0.035, 0.235) text "Show Player's head during sex" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 if Player.check_traits("head_visible"): use options_onoff( Function(Player.remove_trait, "head_visible"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = Player.check_traits("head_visible"), button_shadow = True) else: use options_onoff( Function(Player.give_trait, "head_visible"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = Player.check_traits("head_visible"), button_shadow = True) hbox: fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "CHARACTER INITIATED ACTIONS" anchor (0.0, 0.5) pos (0.035, 0.235) text "Allow characters to initiate actions during sex" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.Character_initiated_Actions"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.Character_initiated_Actions, button_shadow = True) fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "FOOT CONTENT" anchor (0.0, 0.5) pos (0.035, 0.235) text "Enable foot-themed content during sex" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.disable_foot_content"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = not persistent.disable_foot_content, button_shadow = True) hbox: fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "ALTERNATE RMB MODE" anchor (0.0, 0.5) pos (0.035, 0.235) text "Toggle between right mouse button opening the save menu and the Player menu" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 if persistent.alternate_rmb: use options_onoff( [Function(config.keymap["game_menu"].append, "mousedown_3"), SetVariable("persistent.alternate_rmb", False), Function(renpy.clear_keymap_cache)], anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.alternate_rmb, button_shadow = True) else: use options_onoff( [Function(config.keymap["game_menu"].remove, "mousedown_3"), SetVariable("persistent.alternate_rmb", True), Function(renpy.clear_keymap_cache)], anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.alternate_rmb, button_shadow = True) fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "DEFAULT BODY HAIR" anchor (0.0, 0.5) pos (0.035, 0.235) text "Set default body hair for all characters (requires reload or new day)" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.45: font "agency_fb.ttf" size 24 text_align 0.0 use customization_button( SetVariable("persistent.default_body_hair", default_body_hairs[(default_body_hairs.index(persistent.default_body_hair) - 1) % len(default_body_hairs)]), anchor = (0.0, 1.0), pos = (0.5, 0.9), xysize = (int(197*game_resolution), int(181*game_resolution)), image = "images/interface/[interface_resolution]/customization/left.webp", image_zoom = high_resolution_interface_adjustment, image_shadow = True) text "[persistent.default_body_hair!u]" anchor (0.5, 1.0) pos (0.73, 0.74) use customization_button( SetVariable("persistent.default_body_hair", default_body_hairs[(default_body_hairs.index(persistent.default_body_hair) + 1) % len(default_body_hairs)]), anchor = (1.0, 1.0), pos = (0.96, 0.9), xysize = (int(197*game_resolution), int(181*game_resolution)), image = "images/interface/[interface_resolution]/customization/right.webp", image_zoom = high_resolution_interface_adjustment, image_shadow = True) hbox: fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "ENABLE WET HAIR" anchor (0.0, 0.5) pos (0.035, 0.235) text "Allow character's hair to be automatically set to its wet variant when they are wet" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.enable_wet_hair"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.enable_wet_hair, button_shadow = True) fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "CAP STATS BY SEASON (REQUIRES RESTART)" anchor (0.0, 0.5) pos (0.035, 0.235) text "Impose seasonal caps on Love and Trust in the first chapter a character is introduced" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.stat_caps"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.stat_caps, button_shadow = True) # new mod options tab if tab == "mod": hbox: fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "TEXT SPEED: [persistent.text_cps]" anchor (0.0, 0.5) pos (0.035, 0.235) bar value VariableValue("persistent.text_cps", 150) anchor (0.5, 0.0) pos (0.492, 0.58) xysize (int(600*2.0*game_resolution), int(20*2.0*game_resolution)): base_bar Frame("images/interface/full/options/scrollbar.webp") thumb "images/interface/full/options/scrollbar_thumb.webp" thumb_offset int(7*2.0*game_resolution) $ preferences.text_cps = persistent.text_cps fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "AUTO-FORWARD TIME: [persistent.afm_time]" anchor (0.0, 0.5) pos (0.035, 0.235) bar value VariableValue("persistent.afm_time", 30) anchor (0.5, 0.0) pos (0.492, 0.58) xysize (int(600*2.0*game_resolution), int(20*2.0*game_resolution)): base_bar Frame("images/interface/full/options/scrollbar.webp") thumb "images/interface/full/options/scrollbar_thumb.webp" thumb_offset int(7*2.0*game_resolution) $ preferences.afm_time = persistent.afm_time hbox: fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "QUICK MENU TRANSPARENCY: [round(persistent.qm_transparency,1)]" anchor (0.0, 0.5) pos (0.035, 0.235) bar value VariableValue("persistent.qm_transparency", 1.0) anchor (0.5, 0.0) pos (0.492, 0.58) xysize (int(600*2.0*game_resolution), int(20*2.0*game_resolution)): base_bar Frame("images/interface/full/options/scrollbar.webp") thumb "images/interface/full/options/scrollbar_thumb.webp" thumb_offset int(7*2.0*game_resolution) fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "DISABLE QUICK MENU BUTTONS" anchor (0.0, 0.5) pos (0.035, 0.235) hbox anchor (0.5, 1.0) pos (0.5, 0.86): spacing 10 for asset in ("back", "skip", "pref", "save", "q.save", "q.load", "auto"): use base_button( ToggleSetMembership(persistent.qm_buttons, asset), xysize = (int(160*game_resolution), int(150*game_resolution)), selected = asset in persistent.qm_buttons, text = asset.upper(), text_size = 24, animated = False) hbox: fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "ENABLE XP NUMBERS DISPLAY" anchor (0.0, 0.5) pos (0.035, 0.235) text "Show XP numbers instead of a bar on the Skills screen" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.xp_numbers"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.xp_numbers, button_shadow = True) fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "ENABLE BEARDS IN PLAYER PORTRAIT" anchor (0.0, 0.5) pos (0.035, 0.235) text "Select beards in the player customization menu\n(option will be removed if officially supported)" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 if Player.check_traits("beards_unlocked"): use options_onoff( Function(Player.remove_trait, "beards_unlocked"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = Player.check_traits("beards_unlocked"), button_shadow = True) else: use options_onoff( Function(Player.give_trait, "beards_unlocked"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = Player.check_traits("beards_unlocked"), button_shadow = True) hbox: fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "DISABLE SPINNING X-MEN LOGO" anchor (0.0, 0.5) pos (0.035, 0.235) text "Hide the spinning X-Men logo in the main and option menu" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.spinning_logo"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.spinning_logo, button_shadow = True) fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "DISABLE FRIENDSHIP POINTS DISPLAY" anchor (0.0, 0.5) pos (0.035, 0.235) text "Hide the friendship points display on the Friendships screen" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.fps_portraits"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.fps_portraits, button_shadow = True) hbox: fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "DISABLE SCREEN SHAKE (REQUIRES RESTART)" anchor (0.0, 0.5) pos (0.035, 0.235) text "Disable screen shake effects" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.screen_shake"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.screen_shake, button_shadow = True) fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "DISABLE INTERFACE FILTERS" anchor (0.0, 0.5) pos (0.035, 0.235) text "Disable interface filters. Disable Animated Interface under Graphics for only the pulse effect" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.mod_filters"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.mod_filters, button_shadow = True) # new summoner mod options tab if tab == "summoner": hbox: fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "ENABLE SUMMONER" anchor (0.0, 0.5) pos (0.035, 0.235) text "Show the Summoner's interface" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.pepplez_sum"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.pepplez_sum, button_shadow = True) fixed xysize (int(684*2.0*game_resolution), int(172*2.0*game_resolution)): add "images/interface/[interface_resolution]/options/box.webp" zoom interface_adjustment text "ENABLE UNRESTRICTED SUMMONING" anchor (0.0, 0.5) pos (0.035, 0.235) text "WARNING: enables summoning red-marked characters that can cause crashes!" anchor (0.0, 0.0) pos (0.035, 0.45) xsize 0.68: font "agency_fb.ttf" size 24 text_align 0.0 use options_onoff( ToggleVariable("persistent.summon_critical_chars"), anchor = (1.0, 1.0), pos = (0.95, 0.86), selected = persistent.summon_critical_chars, button_shadow = True) vbar value YScrollValue("options_viewport") anchor (0.5, 0.5) pos (0.79, 0.62) xysize (int(20*2.0*game_resolution), 0.6): base_bar Frame("images/interface/full/options/scrollbar_vertical.webp") thumb "images/interface/full/options/scrollbar_vertical_thumb.webp" thumb_offset int(7*2.0*game_resolution) unscrollable "hide" use navigation # Player_menu.rpy: adds XP numbers display screen skills_screen(): default skills_leaderboard_type = "combat" default skills_ability_type = "daily" default skills_ability = None $ leaderboard_Characters = get_leaderboard_Characters(skills_leaderboard_type) add "images/interface/[interface_resolution]/Player_menu/skills_leaderboard_background.webp" zoom interface_adjustment add "images/interface/[interface_resolution]/Player_menu/skills_leaderboard_buttons.webp" zoom interface_adjustment for l, leaderboard_type in enumerate(["combat", "cognitive"]): use skills_leaderboard( SetLocalVariable("skills_leaderboard_type", leaderboard_type), pos = (0.056 + l*0.098, 0.205), xysize = (int(374*game_resolution), int(123*game_resolution)), text = leaderboard_type.upper(), selected = skills_leaderboard_type == leaderboard_type) text "Place" anchor (0.5, 0.5) pos (0.072, 0.306): size 26 text "Name" anchor (0.5, 0.5) pos (0.114, 0.306): size 26 text "Points" anchor (0.5, 0.5) pos (0.226, 0.306): size 26 vbox anchor (0.0, 0.0) pos (0.0585, 0.328) xysize (int(729*game_resolution), 0.557): spacing 2 for c, C in enumerate(leaderboard_Characters): fixed xysize (int(729*game_resolution), int(79*game_resolution)): if C == Player: add "images/interface/[interface_resolution]/Player_menu/skills_leaderboard_Player.webp" zoom interface_adjustment text "[C.first_name]" anchor (0.0, 0.5) pos (0.22, 0.5): size 28 color "#000000" elif C.tag in all_Sprites: add "images/interface/[interface_resolution]/Player_menu/skills_leaderboard_character.webp" zoom interface_adjustment text "[C.public_name]" anchor (0.0, 0.5) pos (0.22, 0.5): size 28 color "#000000" else: add "images/interface/[interface_resolution]/Player_menu/skills_leaderboard_generic.webp" zoom interface_adjustment text "[C.public_name]" anchor (0.0, 0.5) pos (0.22, 0.5): size 28 color "#000000" if c == 0: text "1st" anchor (0.5, 0.5) pos (0.091, 0.602): font "raydis.otf" size 22 color "#000000" elif c == 1: text "2nd" anchor (0.5, 0.5) pos (0.091, 0.602): font "raydis.otf" size 22 color "#000000" elif c == 2: text "3rd" anchor (0.5, 0.5) pos (0.091, 0.602): font "raydis.otf" size 22 color "#000000" $ score = int(C.leaderboard_score[skills_leaderboard_type]) text "[score]" anchor (0.5, 0.5) pos (0.895, 0.5): size 28 color "#000000" text "Leaderboard Resetting In. . ." anchor (0.0, 0.5) pos (0.06, 0.916): size 26 text "[14 - day % 14] Days" anchor (0.5, 0.5) pos (0.227, 0.916): size 26 add "images/interface/[interface_resolution]/Player_menu/skills_leaderboard_lines.webp" zoom interface_adjustment add "images/interface/[interface_resolution]/Player_menu/skills_abilities_top.webp" zoom interface_adjustment for a, ability_type in enumerate(["daily", "mutant"]): if ability_type == "daily": $ text = "PERKS" elif ability_type == "mutant": $ text = "MUTANT ABILITIES" use skills_abilities( SetLocalVariable("skills_ability_type", ability_type), pos = (0.267 + a*0.192, 0.205), xysize = (int(737*game_resolution), int(122*game_resolution)), text = text, selected = skills_ability_type == ability_type) add "images/interface/[interface_resolution]/Player_menu/skills_background_[skills_ability_type].webp" zoom interface_adjustment for ability in all_abilities: if all_abilities[ability]["type"] != skills_ability_type: continue use skills_node( SetLocalVariable("skills_ability", ability), ability, anchor = (0.5, 0.5), pos = all_abilities[ability]["menu_position"], xysize = (int(209*game_resolution), int(193*game_resolution)), selected = skills_ability == ability, image_zoom = 0.5*high_resolution_interface_adjustment, image_shadow = True) add "images/interface/[interface_resolution]/Player_menu/skills_status.webp" zoom interface_adjustment use Player_portrait( anchor = (0.5, 0.5), pos = (0.733, 0.382), zoom = game_resolution) add "images/interface/[interface_resolution]/Player_menu/skills_[Player.scholarship].webp" zoom high_resolution_interface_adjustment if Player.scholarship == "athletic": text "ATHLETICS" anchor (0.5, 0.5) pos (0.755, 0.584): font "agency_fb.ttf" size 30 elif Player.scholarship == "academic": text "ACADEMICS" anchor (0.5, 0.5) pos (0.755, 0.584): font "agency_fb.ttf" size 30 elif Player.scholarship == "artistic": text "ARTS" anchor (0.5, 0.5) pos (0.755, 0.584): font "agency_fb.ttf" size 30 text "LVL" anchor (0.0, 0.5) pos (0.819, 0.239): font "agency_fb.ttf" size 30 text "[Player.level]" anchor (1.0, 0.5) pos (0.87, 0.239): font "agency_fb.ttf" size 30 text "[Player.skill_points]" anchor (0.5, 0.5) pos (0.9, 0.239): font "agency_fb.ttf" size 30 add "images/interface/[interface_resolution]/Player_menu/skills.webp" anchor (0.5, 0.5) pos (0.9145, 0.239) zoom 0.3*interface_adjustment text "XP" anchor (0.0, 0.545) pos (0.819, 0.285): font "agency_fb.ttf" size 30 if Player.XP >= Player.XP_goal: add "images/interface/[interface_resolution]/Player_menu/skills_xp_bar.webp" anchor (1.0, 0.5) pos (0.921, 0.285) zoom interface_adjustment elif Player.level == 1: if not persistent.xp_numbers: bar value Player.XP range Player.XP_goal anchor (1.0, 0.5) pos (0.921, 0.285) xysize (int(277*game_resolution), int(24*game_resolution)): left_bar At(f"images/interface/{interface_resolution}/Player_menu/skills_xp_bar.webp", interface_zoom) right_bar At(f"images/interface/{interface_resolution}/Player_menu/skills_xp_empty_bar.webp", interface_zoom) thumb None thumb_offset 0 else: text "['{:,}'.format(Player.XP)]/['{:,}'.format(Player.XP_goal)]" anchor (1.0, 0.545) pos (0.921, 0.285) size 30 font "agency_fb.ttf" else: if not persistent.xp_numbers: bar value (Player.XP - Player.XP_goal/1.75) range (Player.XP_goal - Player.XP_goal/1.75) anchor (1.0, 0.5) pos (0.921, 0.285) xysize (int(277*game_resolution), int(24*game_resolution)): left_bar At(f"images/interface/{interface_resolution}/Player_menu/skills_xp_bar.webp", interface_zoom) right_bar At(f"images/interface/{interface_resolution}/Player_menu/skills_xp_empty_bar.webp", interface_zoom) thumb None thumb_offset 0 else: text "['{:,}'.format(Player.XP)]/['{:,}'.format(Player.XP_goal)]" anchor (1.0, 0.545) pos (0.921, 0.285) size 30 font "agency_fb.ttf" if Player.level == max_level[chapter]: add "images/interface/[interface_resolution]/Player_menu/skills_max.webp" anchor (0.5, 0.5) pos (0.886, 0.285) zoom high_resolution_interface_adjustment text "MUTANT RANK" anchor (0.0, 0.5) pos (0.819, 0.332): font "agency_fb.ttf" size 25 text "[Player.mutant_rank!u]" anchor (1.0, 0.5) pos (0.921, 0.332): font "agency_fb.ttf" size 25 text "REPUTATION" anchor (0.5, 0.5) pos (0.871, 0.3875): size 28 text "Grade Point Average" anchor (0.0, 0.5) pos (0.8085, 0.427): font "agency_fb.ttf" size 18 if Player.reputation["academic"] == "n/a": pass elif Player.reputation["academic"] >= 3.999: add "images/interface/[interface_resolution]/Player_menu/skills_academic_bar.webp" zoom interface_adjustment anchor (0.0, 0.5) pos (0.8085, 0.462) add "images/interface/[interface_resolution]/Player_menu/skills_max.webp" anchor (0.5, 0.5) pos (0.849, 0.462) zoom high_resolution_interface_adjustment else: bar value (Player.reputation["academic"] - math.floor(Player.reputation["academic"])) range 1.0 anchor (0.0, 0.5) pos (0.8085, 0.462) xysize (int(308*game_resolution), int(26*game_resolution)): left_bar At(f"images/interface/{interface_resolution}/Player_menu/skills_academic_bar.webp", interface_zoom) right_bar At(f"images/interface/{interface_resolution}/Player_menu/skills_empty_bar.webp", interface_zoom) thumb None thumb_offset 0 if Player.reputation["academic"] == "n/a": text "N/A" anchor (0.5, 0.5) pos (0.914, 0.463): font "raydis.otf" size 28 color "#27bfff" elif Player.reputation["academic"] >= 3.999: text "4.0" anchor (0.5, 0.5) pos (0.914, 0.463): font "raydis.otf" size 28 color "#27bfff" elif Player.reputation["academic"] >= 3.99: text "3.99" anchor (0.5, 0.5) pos (0.914, 0.463): font "raydis.otf" size 28 color "#27bfff" else: text "[round(Player.reputation['academic'], 2)]" anchor (0.5, 0.5) pos (0.914, 0.463): font "raydis.otf" size 28 color "#27bfff" text "Danger Room Level" anchor (0.0, 0.5) pos (0.8085, 0.497): font "agency_fb.ttf" size 18 if Player.reputation["combat"] >= 10.0: add "images/interface/[interface_resolution]/Player_menu/skills_combat_bar.webp" zoom interface_adjustment anchor (0.0, 0.5) pos (0.8085, 0.532) add "images/interface/[interface_resolution]/Player_menu/skills_max.webp" anchor (0.5, 0.5) pos (0.849, 0.532) zoom high_resolution_interface_adjustment else: bar value (Player.reputation["combat"] - math.floor(Player.reputation["combat"])) range 1.0 anchor (0.0, 0.5) pos (0.8085, 0.532) xysize (int(308*game_resolution), int(26*game_resolution)): left_bar At(f"images/interface/{interface_resolution}/Player_menu/skills_combat_bar.webp", interface_zoom) right_bar At(f"images/interface/{interface_resolution}/Player_menu/skills_empty_bar.webp", interface_zoom) thumb None thumb_offset 0 text "[math.floor(Player.reputation['combat'])]" anchor (0.5, 0.5) pos (0.914, 0.534): font "raydis.otf" size 28 color "#ed3c3e" text "Popularity Poll" anchor (0.0, 0.5) pos (0.8085, 0.568): font "agency_fb.ttf" size 18 $ number_of_Characters = len(get_leaderboard_Characters("social")) if Player.reputation["social"] >= 1.0: add "images/interface/[interface_resolution]/Player_menu/skills_social_bar.webp" zoom interface_adjustment anchor (0.0, 0.5) pos (0.8085, 0.602) add "images/interface/[interface_resolution]/Player_menu/skills_max.webp" anchor (0.5, 0.5) pos (0.849, 0.602) zoom high_resolution_interface_adjustment else: bar value Player.reputation["social"] range 1/number_of_Characters anchor (0.0, 0.5) pos (0.8085, 0.602) xysize (int(308*game_resolution), int(26*game_resolution)): left_bar At(f"images/interface/{interface_resolution}/Player_menu/skills_social_bar.webp", interface_zoom) right_bar At(f"images/interface/{interface_resolution}/Player_menu/skills_empty_bar.webp", interface_zoom) thumb None thumb_offset 0 text "[math.ceil((1.0 - Player.reputation['social'])*number_of_Characters) + 1]" anchor (0.5, 0.5) pos (0.914, 0.604): font "raydis.otf" size 28 color "#6aea5c" if skills_ability: add "images/interface/[interface_resolution]/Player_menu/skills_box.webp" zoom interface_adjustment text "[all_abilities[skills_ability]['name']!u]" anchor (0.0, 0.5) pos (0.679, 0.679): if len(all_abilities[skills_ability]["name"]) > 18: size 22 elif len(all_abilities[skills_ability]["name"]) > 12: size 24 elif len(all_abilities[skills_ability]["name"]) > 8: size 26 else: size 30 frame anchor (0.5, 0.5) pos (0.801, 0.799) xysize (0.245, 0.202): text "[all_abilities[skills_ability]['description']]" xalign 0.5: font "agency_fb.ttf" size 30 text_align 0.5 if not Player.check_traits(skills_ability) and all_abilities[skills_ability]["cost"] and Player.skill_points >= all_abilities[skills_ability]["cost"]: imagebutton anchor (0.5, 0.5) pos (0.825, 0.679): idle At(f"images/interface/{interface_resolution}/Player_menu/skills_purchase.webp", interface_zoom) hover At(f"images/interface/{interface_resolution}/Player_menu/skills_purchased.webp", interface_zoom) action [ Function(Player.give_trait, skills_ability), Function(Player.History.update, f"bought_skill_{skills_ability_type}")] if skills_ability_type == "daily": text "UNLOCK" anchor (0.5, 0.5) pos (0.825, 0.679): font "agency_fb.ttf" size 25 elif skills_ability_type == "mutant": text "AWAKEN" anchor (0.5, 0.5) pos (0.825, 0.679): font "agency_fb.ttf" size 25 elif not Player.check_traits(skills_ability): add "images/interface/[interface_resolution]/Player_menu/skills_purchase.webp" anchor (0.5, 0.5) pos (0.825, 0.679) zoom interface_adjustment if skills_ability_type == "daily": text "UNLOCK" anchor (0.5, 0.5) pos (0.825, 0.679): font "agency_fb.ttf" size 25 elif skills_ability_type == "mutant": text "AWAKEN" anchor (0.5, 0.5) pos (0.825, 0.679): font "agency_fb.ttf" size 25 else: add "images/interface/[interface_resolution]/Player_menu/skills_purchased.webp" anchor (0.5, 0.5) pos (0.825, 0.679) zoom interface_adjustment text "ACTIVE" anchor (0.5, 0.5) pos (0.825, 0.679): font "agency_fb.ttf" size 25 text "COST" anchor (0.0, 0.5) pos (0.8725, 0.679): font "agency_fb.ttf" size 24 text "[all_abilities[skills_ability]['cost']]" anchor (1.0, 0.5) pos (0.9065, 0.679): font "agency_fb.ttf" size 24 add "images/interface/[interface_resolution]/Player_menu/skills.webp" anchor (0.5, 0.5) pos (0.9145, 0.679) zoom 0.25*interface_adjustment # overlays.rpy: toggle to disable filters screen filter(): layer "filters" fixed xysize (1.0, 1.0): if Player.desire and not persistent.mod_filters: add "images/interface/[interface_resolution]/sex/climax_fringe.webp" zoom interface_adjustment: if persistent.animated_interface: at pulse(Player.desire) else: alpha Player.desire if Player.get_trait("red_power") and not persistent.mod_filters: add "images/interface/[interface_resolution]/Player_power/power.webp" zoom interface_adjustment: if persistent.animated_interface: at tint("#912828"), pulse(Player.get_trait("red_power", default = 0.0)) else: at tint("#912828") alpha Player.get_trait("red_power", default = 0.0) add "images/interface/[interface_resolution]/Player_power/veins.webp" zoom interface_adjustment: if persistent.animated_interface: at tint("#912828"), pulse(Player.get_trait("red_power", default = 0.0)) else: at tint("#912828") alpha Player.get_trait("red_power", default = 0.0) elif Player.power and not persistent.mod_filters: add "images/interface/[interface_resolution]/Player_power/power.webp" zoom interface_adjustment: if persistent.animated_interface: at pulse(Player.power) else: alpha Player.power if Player.get_trait("enhanced_power"): add "images/interface/[interface_resolution]/Player_power/veins_enhanced.webp" zoom interface_adjustment: if persistent.animated_interface: at pulse(Player.get_trait("enhanced_power", default = 0.0)) else: alpha Player.get_trait("enhanced_power", default = 0.0) else: add "images/interface/[interface_resolution]/Player_power/veins.webp" zoom interface_adjustment: if persistent.animated_interface: at pulse(Player.power) else: alpha Player.power at filters_fade_in if persistent.image_filter: add "images/interface/[interface_resolution]/filters/[persistent.image_filter].webp" zoom background_adjustment alpha 0.4 # inventory.rpy: DLSR "camera" description addition. Extra-text fix for game's uppercase-mods is still needed define all_Items["camera"] = { "name": "DLSR camera", "shop_type": "gift", "filter_type": "key_gifts", "description": "Capture your most precious moments like a pro!", "price": 7, "criteria": { "Rogue": (ConditionClass("EventScheduler.check('Rogue_penultimate_penultimate_quirk')"),)}} init 10 python: # taking_class.rpy: removes XP-notifications of NPCs def take_class_after(Characters = None): if not Characters: Characters = [] elif isinstance(Characters, CharacterClass): Characters = [Characters] store.clock = 0 for C in Characters: if C.behavior == "taking_class": C.History.update("attended_class") C.History.update("attended_class_with_Player") elif C.behavior == "teaching": C.History.update("taught_class") C.History.update("taught_class_with_Player") for other_C in Characters: if other_C == C: continue if C.check_traits("no_friends") or other_C.check_traits("no_friends"): continue C.change_friendship(other_C, 1) other_C.change_friendship(C, 1) gained_XP = int(20*C.stat_modifier["XP"]) C.XP += gained_XP if time_index in C.schedule and C.schedule[time_index][1] == C.behavior: del C.schedule[time_index] # update_messages.append("{color=%s}%s{/color} gained {color=%s}%s XP{/color} from {color=%s}Class{/color}" % (C.color, C.name, "#feba00", gained_XP, "#feba00")) reset_behavior(C) change_Character_stat(C, "trust", small_stat) reset_behavior(Player) Player.History.update("attended_class") if Player.check_traits("notetaking"): gained_XP = int(1.2*20*Player.stat_modifier["XP"]*Player.max_stamina) else: gained_XP = int(20*Player.stat_modifier["XP"]*Player.max_stamina) Player.XP += gained_XP update_messages.append("{color=%s}%s{/color} gained {color=%s}%s XP{/color} from {color=%s}Class{/color}" % ("#feba00", Player.first_name, "#feba00", gained_XP, "#feba00")) if clock or time_index == 3: fade_in_from_black(0.4) return # studying.rpy: removes XP-notifications of NPCs def study_after(Characters = None): if not Characters: Characters = [] elif isinstance(Characters, CharacterClass): Characters = [Characters] for C in Characters: C.History.update("studied") C.History.update("studied_with_Player") for other_C in Characters: if other_C == C: continue if C.check_traits("no_friends") or other_C.check_traits("no_friends"): continue C.change_friendship(other_C, 1) other_C.change_friendship(C, 1) gained_XP = int(10*C.stat_modifier["XP"]) C.XP += gained_XP if time_index in C.schedule and C.schedule[time_index][1] == C.behavior: del C.schedule[time_index] # update_messages.append("{color=%s}%s{/color} gained {color=%s}%s XP{/color} from {color=%s}Studying{/color}" % (C.color, C.name, "#feba00", gained_XP, "#feba00")) reset_behavior(C) change_Character_stat(C, "trust", small_stat) reset_behavior(Player) Player.History.update("studied") gained_XP = int(10*Player.stat_modifier["XP"]) Player.XP += gained_XP update_messages.append("{color=%s}%s{/color} gained {color=%s}%s XP{/color} from {color=%s}Studying{/color}" % ("#feba00", Player.first_name, "#feba00", gained_XP, "#feba00")) return # training.rpy: removes XP-notifications of NPCs def train_after(Characters = None): if not Characters: Characters = [] elif isinstance(Characters, CharacterClass): Characters = [Characters] for C in Characters: C.History.update("trained") C.History.update("trained_with_Player") C.sweat += 0.5 for other_C in Characters: if other_C == C: continue if C.check_traits("no_friends") or other_C.check_traits("no_friends"): continue C.change_friendship(other_C, 1) other_C.change_friendship(C, 1) gained_XP = int(10*C.stat_modifier["XP"]) C.XP += gained_XP if time_index in C.schedule and C.schedule[time_index][1] == C.behavior: del C.schedule[time_index] if clock: if time_index not in C.schedule: dice_roll = renpy.random.random() if dice_roll > 0.5: C.schedule[time_index] = ["bg_lockers", "showering"] else: C.schedule[time_index] = ["bg_lockers", "changing"] elif time_index < 3 and time_index not in C.schedule: dice_roll = renpy.random.random() if dice_roll > 0.5: C.schedule[time_index + 1] = ["bg_lockers", "showering"] else: C.schedule[time_index + 1] = ["bg_lockers", "changing"] # update_messages.append("{color=%s}%s{/color} gained {color=%s}%s XP{/color} from {color=%s}Training{/color}" % (C.color, C.name, "#feba00", gained_XP, "#feba00")) reset_behavior(C) change_Character_stat(C, "trust", small_stat) reset_behavior(Player) Player.History.update("trained") Player.sweat += 1 gained_XP = int(10*Player.stat_modifier["XP"]) Player.XP += gained_XP update_messages.append("{color=%s}%s{/color} gained {color=%s}%s XP{/color} from {color=%s}Training{/color}" % ("#feba00", Player.first_name, "#feba00", gained_XP, "#feba00")) return # progression.rpy: removes level-notifications of NPCs def level_up(): if Player.level < max_level[chapter - 1] and Player.XP >= Player.XP_goal: Player.level += 1 update_messages.append("{color=%s}%s{/color} is now {color=%s}Level %s{/color}" % ("#feba00", Player.first_name, "#feba00", Player.level)) elif Player.level == max_level[chapter - 1]: Player.XP = Player.XP_goal for C in GameState.all_Companions: if C.level < max_level[chapter - 1] and C.XP >= C.XP_goal: C.level += 1 # update_messages.append("{color=%s}%s{/color} is now {color=%s}Level %s{/color}" % (C.color, C.name, "#feba00", C.level)) elif C.level == max_level[chapter - 1]: C.XP = C.XP_goal return # database.rpy: new Quests, Friendships, and Relationships tutorial topics, fixed "Attendance Bonus" remark under Status, removed the level cap increase by 5 per chapter remark def get_database_Entries(): Entries = [] Entries.append( DatabaseEntryClass( "info", "Tutorial: Status", "At the top right of your screen are indicators for your stamina levels, the ambient temperature, and any status conditions.\n\nAll activities that advance time require stamina - when your stamina is depleted, time will automatically advance to the next section of the day.\n\nYou can increase your maximum stamina by spending points to learn new mutant abilities.\n\nThe ambient temperature will affect how characters dress and may enable or disable certain events.\n\nThe two main status conditions to be aware of correspond to 1) being sweaty or chlorinated and 2) having high class attendance. The first decreases your Love gains with characters in your proximity, while the latter increases your XP gains.")) Entries.append( DatabaseEntryClass( "info", "Tutorial: Ability Points", "Activities such as studying, training, and attending class net you XP.\n\nLeveling up grants points that can be used to purchase new abilities.\n\nTo learn a new mutant ability, navigate to the Skills menu and select an ability in the Mutant Abilities tab. If you have sufficient points, you can choose to awaken the new ability.\n\nBesides awakening mutant abilities, skill points can also be invested in mundane perks helping in various ways in the Perks tab.")) Entries.append( DatabaseEntryClass( "info", "Tutorial: Earning Money", "You earn a passive income every day that increases with your level.\n\nA more rapid way to earn money is by asking [Charles.public_name] for work by going to his office. You can currently only work once per day, and you must initiate work during the day.")) Entries.append( DatabaseEntryClass( "info", "Tutorial: Quests", "Each companion has main quests available that are required to be accomplished to continue to the next season.\n\nBesides the obligatory main objectives, there are also optional ones that offer additional opportunities to learn more about the characters.\nFor additional information about optional objectives, you can hover the cursor above each one to learn more how to achieve them.\n\nIf you earn enough Love and Trust with each character, you can further develop the relationships to them which are listed as side quests.\n\nNote that you may still complete all optional objectives and side quests after you have already completed the main ones before proceeding to the next season.\nUnfinished side quests can be carried over to the next seasons; optional objectives of main quests not.")) Entries.append( DatabaseEntryClass( "info", "Tutorial: Friendships", "Many activities can be shared with more than one character forming a stronger bond between them.\n\nAsk characters to follow you or text them by phone to come to your location to let them participate in attending class, studying, training, relaxing at the pool, and many other activities together.\n\nFormer acquaintances become good or even best friends the more often they share any activity with you and others together.\n\nNot every character can become Best Friends to everyone else. Such deep connection is reserved only for two companions as pair.\nSome characters might not even understand the meaning of friendships due to difficulties in their former life, so it is highly encouraged to help those overcoming their social problems.")) Entries.append( DatabaseEntryClass( "info", "Tutorial: Dates", "If a character has communicated that they wish to go on a date with you, then you can ask them on a date via text.\n\nDates start in the evening and require you to have no prior committments for the evening and night.")) Entries.append( DatabaseEntryClass( "info", "Tutorial: Relationships", "After dating a companion and increasing enough Love and Trust, you are ready to move forward to form a stronger partnership.\nYou can either wait for your companion to make the first step or ask her yourself if she wants to become your girlfriend.\n\nIf you don't feel committed to only a single partner, you could also try to woo several ones, but be aware you need to build a lot more Trust for such polyamorous relationship before they accept it.\nAfter accepting to let you have multiple partners, you also need to ask each girlfriend first who else you want to date. They will only accept others who are at least Friend to them.\n\nThe final step in a relationship is if your companion confesses her love to you.\nThis is also the time you may have sexual intercourse with her.")) Entries.append( DatabaseEntryClass( "info", "Tutorial: Intimacy", "Being a good lover comes down to a single attribute: consideration of the needs and wants of your partner(s). Actively communicating and listening to your partner(s) helps to ensure an enjoyable experience for everyone.\n\nDuring the sex minigame, your goal is to maximize pleasure (i.e. orgasms) for both yourself and your partner(s) while keeping things fresh and interesting. Put plainly, make your partner(s) and yourself orgasm as many times as possible by using as many unique actions as you can for a sizable Love bonus.")) Entries.append( DatabaseEntryClass( "info", "Tutorial: Wardrobe", "Accessing a character's wardrobe requires a certain level of intimacy - when this threshold is reached, the wardrobe menu will become accessible through interacting with the character.\n\nCharacters will only agree to wear outfits with shame values below their current caps. Caps for public outfits and special outfits (e.g. for exercise or swimming) are listed in the top left and increase as your relationship with a character grows. Outfits not designated for public use require lower stats.\n\nIn addition to customizing your own outfits, purchasing new clothing items will automatically contribute to the pool of outfits character's will pick out for themselves. Both default and custom outfits can be disabled to remove them from the selection pool.")) body = "The Xavier Institute for Higher Learning (former name Xavier School for Gifted Youngsters) is the public name for the X-Mansion and its surrounding area.\n\nDepicted as a private school to the general public, the mansion is, in reality a shelter to protect and nurture individuals with the X-Gene.\n\nThe estate is the private property of Charles Francis Xavier. Inherited by him as a younger man, the mansion has been in the Xavier family for generations. The history of the estate dates back to 1838 when it was built by Cornellius Xavier, the man that established the Xavier family fortune. He built this money in banking, forestry, and shipping concerns. The original mansion was much smaller, mostly used as a summer home for his family." body += "\n\nIn late 1881, Malcolm Francis Xavier advocated to modernize the residence, starting with the installation of electric lighting. During this process, it was determined that the building was suffering from severe structural issues. Malcolm commissioned Stanford White to build a mansion more fitting of the family's stature. The construction process finished in 1884 and was considered the most modern residence in Westchester." body += "\n\nAfter the turn of the century, Francis moved his family to the mansion full time, shifted his family wealth towards its current portfolio and added both wings to the mansion. In 1903, Francis hired the designer Arnold Constable to update the interior look of the mansion." body += "\n\nThe next big change to the mansion would only happen decades later. Charles Xavier's stepfather was a man who took the threat of nuclear war very seriously and hired a team to build a bunker under the mansion that could protect the occupants. What started as a small living area turned into a sprawling network of rooms, every bit as complex as the above-ground mansion. This would serve Charles well, when the time came to put his own plans into action." Entries.append( DatabaseEntryClass( "info", "The Institute", body)) body = "The basement area has seen multiple renovations over the years. To access the basement, residents must take a hidden elevator. The elevator performs biometric scans to confirm authorized access to the basement facilities." body += "\n\nThe basement features an emergency high-speed transport (marked in yellow on the map) as well as various security areas (marked in red). There are multiple layers of security defenses: panels in the walls reveal turrets capable of incapacitating unwelcome visitors. State-of-the-art surveillance cameras survey the area and are able to scan in multiple visual frequencies to detect even invisible or camouflaged targets. Laser grids and forcefields are also built into multiple areas to contain and control invaders if required." body += "\n\nDANGER ROOM: The mansion's primary training facility. Thanks to the various machines, holograms, forcefields, and other technology installed, the Danger Room is capable of running high-level combat training simulations within almost any parameter set imaginable. The room comes equipped with its own AI to further support and assist its users. The AI is constantly upgraded to support the diverse needs of the student body." body += "\n\nLOCKER ROOM: Located near the Danger Room and the gym for convenience, the locker room is co-ed and features showers for use after heavy training regiments or pool usage." body += "\n\nGYM: Equipped with the best training equipment available on the market, the gym allows students to focus on physical training without any additional distractions or requirements." body += "\n\nMACHINE ROOMS: This room houses the water heater and furnace, as well as various maintenance tools and spare parts." body += "\n\nR&D LAB: The research and development lab fulfills a multitude of needs: from research to creating new gear and suits, R&D is capable of handling virtually all of the school's needs." body += "\n\nCEREBRO: Professor Xavier's pride and joy, CEREBRO can be used to detect mutants all around the world. The Professor uses it to track and, if necessary, organize rescues for people with the X-Gene." body += "\n\nINFIRMARY: With advanced medical technology, this infirmary is better equipped than any hospital in the world." Entries.append( DatabaseEntryClass( "info", "The Institute: Basement", body)) body = "The first floor is the main area of the mansion, with all the necessary facilities for day-to-day life." body += "\n\nGROUNDS: The outside area of the mansion, the grounds are well-tended year-round. The grounds offer various places for students to relax and congregate." body += "\n\nMAIN HALLWAY: The entrance of the mansion gives access to the second floor with a large staircase. It also leads to the kitchen, ante room, and reception room. Some people use it as a meeting point when they go to the city or mall as a group." body += "\n\nKITCHEN: The kitchen would be the envy of any world-class chef. Students are permitted to use the kitchens to cook their own meals if they wish, but permission is required in advance." body += "\n\nANTE ROOM: Serves as a waiting room for appointments and guests." body += "\n\nHEADMASTER'S STUDY: Xavier's office. The Professor also has his own private quarters, accessible only from this office. This room connects to the ante room." body += "\n\nLIBRARY: The mansion boasts an extensive library, with books that have belonged to the family for generations. The library is primarily used as a study area and occasional hangout spot for students. This room has access to the classroom and reception room." body += "\n\nCLASSROOMS: The classrooms are designed with a modern design focus that compliments the rest of the mansion. Several of the classrooms overlook the pool. This room has access to the library." body += "\n\nRECEPTION ROOM: When students receive visits from friends or family, they are welcomed here. The room is designed to be as comfortable and welcoming as possible." body += "\n\nDINING ROOM: The main dining room is where students gather to eat, study, and hang out. The dining room connects to the kitchen and recreation room." body += "\n\nRECREATION ROOM: The rec room offers all the conveniences the students could possibly ask for: large, plush sofas, a 100-inch TV, game consoles, pool tables, etc. This room has access to the reception room and dining room." body += "\n\nPOOL: An Olympic-sized swimming pool that is occasionally used for training and exercise, but is more commonly used for fun. The pool has access to the reception room." Entries.append( DatabaseEntryClass( "info", "The Institute: First Floor", body)) body = "The second floor contains most of the resident dormitories. In addition to the students' individual rooms, there are four larger rooms with shared accommodation." body += "\n\nAll rooms feature standard modern conveniences - internet access, cable, as well as safety features and first aid boxes." Entries.append( DatabaseEntryClass( "info", "The Institute: Second Floor", body)) body = "The top floor of the mansion is where most instructors and mansion veterans reside." body += "\n\nThe biggest room in this floor is reserved for Ororo Munroe and her greenhouse. Several of the species of plant grown in the greenhouse are very rare or otherwise hard to grow, with some used for medicinal purposes." Entries.append( DatabaseEntryClass( "info", "The Institute: Attic", body)) return Entries # text replacements def replace_text(t): t = t.replace("Bathe ", "Shower ") t = t.replace("Paizuri", "Titjob") t = t.replace("Dlsr", "DLSR") t = t.replace("Mma", "MMA") t = t.replace("veiner", "wiener") t = t.replace("Remain celibate", "Remain a virgin") t = t.replace("$1000", "$1,000") t = t.replace("$5000", "$5,000") t = t.replace("$10k", "$10,000") t = t.replace("$50k", "$50,000") t = t.replace("3 or", "three or") return t config.replace_text = replace_text