init -5 python: from collections import namedtuple AchievementKind = namedtuple("AchievementKind", ("category", "name", "description", "icon", "progression", "progression_max")) AchievementKind.title = AchievementKind.name define achievements_db = { # GENERAL "tooltip": AchievementKind("general", "A big surprise", "Discovered more than the tip of the tool inside the settings.", "interface/icons/silver_scroll.webp", None, None), "Credits": AchievementKind("general", "New game, who this?", "Watched the credits.", "interface/icons/silver_scroll.webp", None, None), "gold": AchievementKind("general", "Gold Digger", "Acquired 10,000 gold coins.", "interface/icons/gold.webp", "states.env.gold", 10000), "drunkard": AchievementKind("general", "Drunken Master", "Acquired 25 bottles of wine.", "interface/icons/wine.webp", "wine_ITEM.owned", 25), "workaholic": AchievementKind("general", "Workaholic", "Completed five full reports.", "interface/icons/generic_scroll.webp", "states.paperwork_reports_times", 5), "fireplace": AchievementKind("general", "Feel the Heat", "Started fire 5 times.", "images/rooms/main_room/fireplace/fireplace_idle.webp", "states.fireplace_started_times", 5), "peta": AchievementKind("general", "I think I forgot something...", "Forgot to feed the bird 50 days in a row.", "images/rooms/main_room/phoenix/phoenix_01.webp", "(states.env.day - states.bird_fed_times)", 50), "jerkoff": AchievementKind("general", "Regular Wand Polish", "Jerked off 10 times.", "images/rooms/main_room/phoenix/phoenix_01.webp", "states.jerked_off_times", 10), "petpal": AchievementKind("general", "Regular stroking", "Petted the bird 25 times.", "images/rooms/main_room/phoenix/phoenix_01.webp", "states.bird_petted_times", 25), "postman": AchievementKind("general", "Poster Boy", "Bought all posters from the store.", "interface/icons/agrabah_poster.webp", None, None), "hats": AchievementKind("general", "Mad Hatter", "Bought all hats from the store.", "interface/icons/icon_gambler_hat.webp", None, None), "bros": AchievementKind("general", "Bros before hoes", "Became best pals with Snape.", "interface/icons/head/snape.webp", None, None), "decorator": AchievementKind("general", "Decorator", "Applied a decoration.", "interface/icons/stag_trophy.webp", None, None), # PROGRESSION "firstpotion": AchievementKind("progression", "Brewing 101", "Brewed your first potion.", "interface/icons/potion_generic.webp", None, None), "unlockher": AchievementKind("progression", "Granger Danger", "Unlocked Hermione Granger.", "interface/icons/head/hermione.webp", None, None), "unlockcho": AchievementKind("progression", "Chang Dynasty", "Unlocked Cho Chang.", "interface/icons/head/cho.webp", None, None), "unlocklun": AchievementKind("progression", "Looney Tunes", "Unlocked Luna Lovegood.", "interface/icons/head/luna.webp", None, None), "unlockast": AchievementKind("progression", "Green Peas", "Unlocked Astoria Greengrass.", "interface/icons/head/astoria.webp", None, None), "unlockton": AchievementKind("progression", "Nymphadoreador", "Unlocked Nymphadora Tonks.", "interface/icons/head/tonks.webp", None, None), "unlocksus": AchievementKind("progression", "Boner", "Unlocked Susan Bones.", "interface/icons/head/susan.webp", None, None), "unlocksna": AchievementKind("progression", "Strictly colleagues", "Unlocked Severus Snape.", "interface/icons/head/snape.webp", None, None), "overwhored": AchievementKind("progression", "Overwhored", "Fully corrupted one of the girls.", "interface/icons/head/hermione.webp", None, None), "herstrip": AchievementKind("progression", "Dance lessons", "Allowed Hermione to dance naked in front of Snape.", "interface/icons/head/hermione.webp", None, None), "herkiss": AchievementKind("progression", "First Kiss", "You made out with Hermione, or rather your cock did.", "interface/icons/head/hermione.webp", None, None), "hertits": AchievementKind("progression", "Boobs Lover", "Stuck a dick between the valley of plenty.", "interface/icons/head/hermione.webp", None, None), "headlib": AchievementKind("progression", "Head Librarian", "Had oral lessons with Hermione.", "interface/icons/head/hermione.webp", None, None), "nerdgasm": AchievementKind("progression", "Nerdgasm", "Done the deed with Hermione.", "interface/icons/head/hermione.webp", None, None), "start": AchievementKind("progression", "Welcome to Hogwarts!", "Finished the intro.", "interface/icon.webp", None, None), "ending": AchievementKind("progression", "Bittersweet Farewell", "Reached the ending.", "interface/icons/silver.webp", None, None), # EVENTS "satan": AchievementKind("events", "Daddy Lucifer", "Made a pact with the right devil.", "interface/icons/phone.webp", None, None), "vibin": AchievementKind("events", "Just Vibin", "Brought Hermione pure joy while she wore vibrators in front of her friends.", "interface/icons/box-o-fun.webp", None, None), "tittypotion": AchievementKind("events", "Tig Ol' bitties", "Used a potion to increase one's breast size to the max.", "interface/icons/breast_potion.webp", None, None), "kittypotion": AchievementKind("events", "Here kitty, kitty!", "Hermione overdosed on polyjuice potion.", "interface/icons/cat_potion.webp", None, None), "daddy": AchievementKind("events", "Who's your daddy?", "Been called a daddy.", "interface/icons/head/hermione.webp", None, None), "knock": AchievementKind("events", "*Knock* *knock*", "Told Hermione to fuck off.", "images/rooms/main_room/door/door_idle.webp", None, None), "pantiesfap": AchievementKind("events", "I sneezed on them...", "Rubbed one out on someone's panties.", "characters/genie/chibis/jerk_off/02.webp", None, None), "Cardwin": AchievementKind("events", "Time to duel", "Won a card game duel.", "interface/icons/cards.webp", None, None), "mirror": AchievementKind("events", "Mirror, mirror on the wall..", "Found the Room of Requirements.", "images/rooms/room_of_requirement/mirror_hover.webp", None, None), "busted": AchievementKind("events", "BUSTED!", "Got busted for busting a nut.", "interface/icons/head/hermione.webp", None, None), # SECRETS "safetyfirst": AchievementKind("secrets", "Safety First", "Wore a condom when the time was right.", "interface/icons/condoms.webp", None, None), "puzzle": AchievementKind("secrets", "Brainiac", "Solved an incredibly complex sliding tiles puzzle.", "interface/icons/item_potion.webp", None, None), "flashback": AchievementKind("secrets", "Flashback", "Rolled back to the future at the right moment.", "interface/icons/cards.webp", None, None), } init python hide: for name in achievements_db: achievement.register(name) init python: # intentionaly not a define nor a default __popup_stack = [] config.after_default_callbacks.append(__popup_stack.clear) config.always_shown_screens.append("achievement_main") screen achievement_main(): layer "interface" vbox: for id index id in __popup_stack[:3]: use achievement_window(msg=achievements_db[id].title, title="Achievement unlocked!", icon=achievements_db[id].icon) timer 6 action Function(__popup_stack.remove, id) label popup(msg="", title="", icon=None, xpos=0, ypos=60, sound=True, soundfile='sounds/achievement.ogg'): if sound: play sound soundfile hide screen achievement_window show screen achievement_window(msg=msg, title=title, icon=icon, xpos=xpos, ypos=ypos) return screen achievement_window(msg="", title="", icon=None, xpos=0, ypos=60): tag popup_window layer "interface" frame: style "empty" at popup_animation(time=5.0, xx=-410) pos (xpos, ypos) xsize 410 ysize 96 add gui.format("interface/achievements/{}/box.webp") if icon: frame: style "empty" pos (6, 6) xsize 84 ysize 84 $ image_zoom = crop_image_zoom(icon, 84, 84) if 'head' in icon: add image_zoom align (0.5, 1.0) yoffset -1 else: add image_zoom align (0.5, 0.5) add "interface/achievements/glass.webp" frame: style "empty" xpos 96 xsize 314 vbox: ypos 12 spacing 10 xalign 0.5 text title size 18 xalign 0.5 text msg size 14 xalign 0.5 timer 6.0 action Hide("achievement_window") transform rotate_circular(t=7): animation subpixel True rotate 0 linear t rotate 360 repeat init python in achievements: def validate(): """Validate icons and progression flags""" for i in renpy.store.achievements_db.values(): if not renpy.loadable(i.icon): raise IOError(repr(i.icon)) # if i.progression and not isinstance(eval(i.progression), (int, float)): # raise TypeError(f"Progression flag must return a float or an integer - {i.progression}") validate() def unlock(id, silent=False): if renpy.store._in_replay: return if not renpy.store.achievement.has(id): renpy.store.achievement.grant(id) if not silent: renpy.play('sounds/achievement.ogg') renpy.store.__popup_stack.append(id) status = renpy.store.achievement.has lock = renpy.store.achievement.clear def get_list(category=None): if category: items = filter((lambda x: category==renpy.store.achievements_db[x].category), renpy.store.achievements_db) else: items = renpy.store.achievements_db items = sorted(items, key=lambda x: renpy.store.natsort_key(renpy.store.achievements_db[x].title)) return items def get_list(category=None): if category: items = filter((lambda x: category==renpy.store.achievements_db[x].category), renpy.store.achievements_db) else: items = renpy.store.achievements_db # Sort titles items = sorted(items, key=lambda x: renpy.store.natsort_key(renpy.store.achievements_db[x].title)) # Sort unlocks items = sorted(items, key=lambda x: renpy.store.achievement.has(x)) return items def get_categories(): return set(item.category for item in renpy.store.achievements_db.values()) def get_percentage(category=None): if category: items = list(filter((lambda x: category==renpy.store.achievements_db[x].category), renpy.store.achievements_db)) else: items = renpy.store.achievements_db total_achievements = len(items) unlocked_achievements = sum(1 for x in items if renpy.store.achievement.has(x)) return round((unlocked_achievements / total_achievements) * 100) label achievements(inter_pause=True): $ disable_game_menu() if inter_pause: # Ensures all irrelevant screens are hidden before capturing the surface tree with Pause(0.2) call screen achievements $ enable_game_menu() jump main_room_menu screen achievements(): modal True layer "interface" zorder 0 style_prefix "achievements" default navigation_atl = navigation_show default last_frame = (screenshot.capture() or screenshot.image) default navigation_last_frame_atl = navigation_last_frame_show default navigation_exit = False default category = None default menu_categories = achievements.get_categories() default menu_items = achievements.get_list(category) add last_frame at navigation_last_frame_atl if navigation_exit: timer 0.4 action Return() frame: style "empty" align (0.5, 0.5) at navigation_atl vbox: style_prefix "navigation_subtabs" pos (286, 170) at navigation_subtabs_show textbutton _("All") action [SetScreenVariable("category", None), SetScreenVariable("menu_items", achievements.get_list())] selected (category==None) at navigation_tabs for i in menu_categories: textbutton "[i.capitalize()]" action [SetScreenVariable("category", i), SetScreenVariable("menu_items", achievements.get_list(i))] selected (category==i) at navigation_tabs null height 35 textbutton _("Return") action [SetScreenVariable("navigation_last_frame_atl", navigation_last_frame_hide), SetScreenVariable("navigation_atl", navigation_hide), SetScreenVariable("navigation_exit", True)] keysym ["game_menu", "achievements"] at navigation_tabs frame: label _("Achievements") text "([achievements.get_percentage()]%)" pos (108, -3) # Add items viewport: ypos 32 scrollbars "vertical" mousewheel True draggable "touch" vbox: for item in menu_items: $ item_unlocked = achievement.has(item) $ item_data = achievements_db[item] $ item_color = "#ffffff" if item_unlocked else "#8d8d8d" fixed: fit_first True button: hbox: fixed: xysize (48, 48) add crop_image_zoom(item_data.icon, 48, 48, not item_unlocked) xysize (48, 48) fit "contain" align (0.5, 0.5) null width 5 vbox: text "[item_data.title]" color item_color text "[item_data.description]" color item_color style "achievements_text_small" action NullAction() if item_unlocked: add "interface/topbar/icon_check.webp" xysize (24, 24) yalign 0.5 if item_data.progression: if item_unlocked: bar value StaticValue(1.0) else: bar value StaticValue(eval(item_data.progression), item_data.progression_max) style "achievements_bar_disabled" add "frame_spacer" xalign 0.5 xsize 500 style achievements_viewport is viewport: xalign 0.5 ymaximum 397 style achievements_vbox is frame_vbox: ypos 0 yspacing 0 xalign 0 style achievements_frame is frame style achievements_label is frame_label style achievements_label_text is frame_label_text style achievements_text is frame_text: xalign 0 style achievements_text_small is achievements_text: xalign 0 size 12 style achievements_button is frame_button: xfill True yminimum 48 style achievements_button_text is frame_button_text style achievements_bar is player_bar: xmaximum 400 yalign 1.0 xpos 78 ysize 10 yoffset -2 style achievements_bar_disabled is achievements_bar: left_bar Frame(Transform(Image("gui/creamy_pumpkin_pie/player/player_bar_full.png", oversample=4), matrixcolor=BrightnessMatrix(-0.5)), 24, 0, tile=False) right_bar Frame(Transform(Image("gui/creamy_pumpkin_pie/player/player_bar_empty.png", oversample=4), matrixcolor=BrightnessMatrix(-0.5)), 24, 0, tile=False)