WTS/game/scripts/shops/dress/menu.rpy

410 lines
15 KiB
Plaintext

# Functions (Initialised after wardrobe)
init 5 python in clothing_store:
import functools
get_icon = renpy.store.wardrobe.get_icon # Simple Proxy since both interfaces share the same code
parcel_callbacks = []
def checkout():
scope = renpy.get_screen("clothing_store_interface").scope
cart = scope["cart"]
renpy.call_screen_in_new_context("clothing_store_checkout", cart)
def checkout_confirm():
scope = renpy.get_screen("clothing_store_checkout").scope
transit_time = scope["transit_time"]
cart = scope["cart"]
renpy.play("sounds/money.ogg")
scope["navigation_atl"] = renpy.store.gui_modal_hide
scope["fade_atl"] = renpy.store.wardrobe_fade_hide
renpy.call_in_new_context("clothing_store_checkout", transit_time, cart)
curry = renpy.curry(renpy.store.execute_callbacks)(parcel_callbacks) if parcel_callbacks else None
renpy.store.Parcel(contents=[(i, 1) for i in cart], wait=transit_time, func=curry).send()
scope["navigation_exit"] = True
exit()
def checkout_cancel():
scope = renpy.get_screen("clothing_store_checkout").scope
scope["navigation_atl"] = renpy.store.gui_modal_hide
scope["fade_atl"] = renpy.store.wardrobe_fade_hide
scope["navigation_exit"] = True
renpy.restart_interaction()
def change_section(section):
scope = renpy.get_screen("clothing_store_interface").scope
scope["character"] = renpy.store.get_character_object(section)
scope["selected_section"] = section
scope["selected_item"] = next(outfits(section), None)
def add_remove_outfit(outfit):
scope = renpy.get_screen("clothing_store_interface").scope
cart = scope["cart"]
if outfit in cart:
# Remove the outfit from the cart if it's already there and there are more than one item
cart ^= {outfit}
elif len(cart) < 5:
# Add the outfit to the cart if it's not already there and there are less than five items
cart |= {outfit}
else:
renpy.sound.play("sounds/fail.ogg")
renpy.call_in_new_context("clothing_store_cart_full")
def select_outfit(outfit):
scope = renpy.get_screen("clothing_store_interface").scope
scope["selected_item"] = outfit
renpy.restart_interaction()
def exit():
scope = renpy.get_screen("clothing_store_interface").scope
renpy.play("sounds/curtain_close.ogg")
# Handle exit animation
scope["navigation_last_frame_atl"] = renpy.store.navigation_last_frame_hide
scope["navigation_atl"] = renpy.store.wardrobe_hide
scope["information_atl"] = renpy.store.wardrobe_fade_hide
scope["character_atl"] = renpy.store.wardrobe_character_hide
scope["navigation_exit"] = True
# Reset states
renpy.restart_interaction()
@functools.cache
def characters():
# Filter out side characters from the dolls list
return [doll for doll in renpy.store.states.dolls if doll != "hooch"]
def outfits(section):
scope = renpy.get_screen("clothing_store_interface").scope
character = scope["character"]
# Sort the outfits by price in ascending order
sorted_outfits = sorted((x for x in reversed(character.outfits) if not x.unlocked and x.price > 0), key=lambda outfit: outfit.price)
return iter(sorted_outfits)
def discuss(outfit):
renpy.store._skipping = True
renpy.suspend_rollback(False)
renpy.block_rollback()
renpy.call_in_new_context("clothing_store_discuss", outfit)
renpy.store._skipping = False
def wheelmenu(outfit):
scope = renpy.get_screen("clothing_store_interface").scope
character = scope["character"]
cart = scope["cart"]
exit_action = renpy.store.Function(renpy.hide_screen, "wheelmenu")
select_action = renpy.store.Function(select_outfit, outfit)
add_remove_action = renpy.store.Function(add_remove_outfit, outfit)
d = {
_("select"): (renpy.store.Text("✅", align=(0.5, 0.5)), [exit_action, select_action])
}
if outfit in cart:
d[_("Remove from cart")] = (renpy.store.Text("🛒", align=(0.5, 0.5)), [exit_action, add_remove_action])
else:
d[_("Add to cart")] = (renpy.store.Text("🛒", align=(0.5, 0.5)), [exit_action, add_remove_action])
btns = renpy.store.create_wheelmenu(d)
renpy.play("sounds/qubodup-click1.ogg")
renpy.show_screen("wheelmenu", btns, pos=None, close_action=exit_action)
def character_in_cart(character):
scope = renpy.get_screen("clothing_store_interface").scope
cart = scope["cart"]
for outfit in cart:
if outfit.char.name == character:
return True
return False
@functools.cache
def mannequin(name): # Name used for cache ref only
scope = renpy.get_screen("clothing_store_interface").scope
character = scope["character"]
return renpy.store.Transform(character.body.image, matrixcolor=renpy.store.SaturationMatrix(0.0))
# Context
label clothing_store_interface(inter_pause=True):
$ disable_game_menu()
play sound "sounds/curtain_open.ogg"
if inter_pause:
# Ensures all irrelevant screens are hidden before capturing the surface tree
with Pause(0.2)
$ clothing_store.parcel_callbacks = [] # Clears the parcel callbacks upon the next call to screen clothing_store_interface
call screen clothing_store_interface
$ enable_game_menu()
# jump expression f"{states.active_girl}_requests"
jump clothing_store.exit
# Interface
screen clothing_store_interface():
layer "interface"
zorder 0
style_prefix "store"
default navigation_atl = wardrobe_show
default information_atl = wardrobe_fade_show
default character_atl = wardrobe_character_show
default last_frame = (screenshot.capture() or screenshot.image)
default navigation_last_frame_atl = navigation_last_frame_show
default navigation_exit = False
default character = get_character_object("tonks")
default selected_section = "tonks"
default selected_item = next(clothing_store.outfits(selected_section), None)
default cart = set()
$ total_price = sum([item.price for item in cart])
$ total_gold = states.env.gold-total_price
$ can_afford = states.env.gold >= total_price
add last_frame at navigation_last_frame_atl
add "gui_fade_both" at gui_fade
if navigation_exit:
timer 0.4 action Return()
if selected_item:
add selected_item.image align (1.0, 1.0) zoom 0.6 at character_atl
frame:
style "empty"
at information_atl
add "gui_fade_bottom"
vbox:
xpos 550
yoffset -10
yalign 1.0
xsize 350
label selected_item.name align (0.0, 1.0)
add "frame_spacer" xsize 350
text selected_item.desc align (0.0, 1.0)
vbox:
pos (972, 468)
vbox:
xoffset -36
text _("[states.env.gold]G") xalign 1.0
text _("-[total_price]G") xalign 1.0
add "frame_spacer" xsize 100
if total_gold >= 0:
text _("[total_gold]G") color "#0ead00" xalign 1.0
else:
text _("[total_gold]G") color "#ad0000" xalign 1.0
label _("G") + str(selected_item.price) xoffset -50 style "store_pricetag_label"
else:
add clothing_store.mannequin(selected_section) align (1.0, 1.0) zoom 0.6 at character_atl
frame:
style "empty"
at navigation_atl
vbox:
style_prefix "navigation_tabs"
pos (540, 300)
at navigation_tabs_show
textbutton _("Discuss") action Function(clothing_store.discuss, selected_item) sensitive (selected_item != None) style "navigation_tabs_button_special" at navigation_tabs
textbutton (_("Remove from cart") if selected_item in cart else _("Add to cart")) action Function(clothing_store.add_remove_outfit, selected_item) selected (selected_item in cart) sensitive (selected_item != None) style "store_tabs_button_add_remove" at navigation_tabs
textbutton _("Checkout") action clothing_store.checkout sensitive (can_afford and cart and (selected_item != None)) at navigation_tabs
null height 35
textbutton _("Exit") action clothing_store.exit keysym "K_ESCAPE" at navigation_tabs
frame:
at navigation_atl
vbox:
# Sections
hbox:
spacing 0
for i in clothing_store.characters():
button:
xysize (64, 64)
add clothing_store.get_icon(i) xysize (64, 64)
if clothing_store.character_in_cart(i):
add Transform(Text("🛒"), align=(1.0, 1.0), size=(24, 24))
tooltip i
action Function(clothing_store.change_section, i) selected (selected_section == i)
null height 3
add "frame_spacer" xsize 500 xalign 0.5
null height 3
if not selected_item:
text _("SOLD OUT!") size 96 at transform:
align (0.5, 0.5)
rotate -45
# Outfit List
vpgrid:
cols 5
spacing 4
mousewheel True
scrollbars "vertical"
for outfit in clothing_store.outfits(selected_section):
button:
style "store_rectangular_button"
add outfit.button.child
label "G[outfit.price]" style "store_pricetag_label_small"
if outfit in cart:
add Transform(Text("🛒"), align=(1.0, 1.0), size=(24, 24))
if renpy.android:
action Function(clothing_store.wheelmenu, outfit)
else:
action Function(clothing_store.select_outfit, outfit)
alternate Function(clothing_store.wheelmenu, outfit)
selected (selected_item == outfit)
screen clothing_store_checkout(cart):
modal True
layer "interface"
zorder 0
style_prefix "frame"
default navigation_atl = gui_modal_show
default fade_atl = wardrobe_fade_show
default navigation_exit = False
add "gui_fade_both" at fade_atl
default fast_delivery = False
default fast_delivery_fee = 45 + ( (len(cart)-1) * 20 )
$ total_price = sum([item.price for item in cart]) + (fast_delivery_fee if fast_delivery else 0)
$ total_gold = states.env.gold-total_price
$ can_afford = states.env.gold >= total_price
$ transit_time = (len(cart)+1)//2 if fast_delivery else len(cart)+1
if navigation_exit:
timer 0.4 action Return()
frame:
at navigation_atl
label _("Checkout")
vbox:
xminimum 496
hbox:
style "store_checkout_hbox"
for item in cart:
button:
xysize (96, 168)
style "store_rectangular_button"
add item.button.child
label "G[item.price]" style "store_pricetag_label_small"
action NullAction()
textbutton _("Fast Delivery") action ToggleScreenVariable("fast_delivery", True, False) style "store_checkbox_button"
text _("Delivery Time: [transit_time] day(s)") color "#ffffff" xalign 0.0 style "store_checkbox_button_text"
vbox:
style_prefix "store_checkout"
text _("[states.env.gold]G") xalign 1.0
text _("-[total_price]G") xalign 1.0
add "frame_spacer" xsize 200 xalign 1.0
text _("[total_gold]G") color ("#0ead00" if can_afford else "#ad0000") xalign 1.0
null height 20
hbox:
xalign 0.5
yalign 1.0
textbutton _("Confirm") action clothing_store.checkout_confirm sensitive (can_afford)
textbutton _("Cancel") action clothing_store.checkout_cancel
style store_rectangular_button is wardrobe_item_button:
xysize (96, 168)
background Transform("wheelmenu_frame_vertical", xysize=(96,168))
hover_background At(Transform("wheelmenu_frame_opaque_vertical", xysize=(96,168)), wheelmenu_hover_anim)
selected_background Fixed(Transform("wheelmenu_frame_vertical", xysize=(96,168)), At(Transform("interface/achievements/glow.webp", align=(0.5, 0.5), size=(96, 96), alpha=0.5), rotate_circular))
selected_hover_background Fixed(At(Transform("wheelmenu_frame_vertical", xysize=(96,168)), wheelmenu_hover_anim), At(Transform("interface/achievements/glow.webp", align=(0.5, 0.5), size=(96, 96), alpha=0.5), rotate_circular))
selected_foreground None
style store_frame is wardrobe_frame
style store_button is wardrobe_button
style store_text is wardrobe_text:
color "#FFFFFF"
style store_label_text is wardrobe_text:
color "#EA8D60"
style store_pricetag_label:
background Image("gui/creamy_pumpkin_pie/store/price_tag.png", oversample=3)
style store_pricetag_label_text:
anchor (1.0, 0.5)
text_align 1.0
pos (110, 30)
color "#000000"
outlines [(2, "#8BA5D9", 1, 1)]
hinting "bytecode"
size 24
style store_pricetag_label_small:
align (0.0, 1.0)
xysize (68, 28)
background Frame(Image("gui/creamy_pumpkin_pie/store/price_tag.png", oversample=6), 20, 10, tile=False, fit="contain")
style store_pricetag_label_small_text:
anchor (1.0, 0.5)
text_align 1.0
pos (50, 16)
color "#000000"
outlines [(1, "#8BA5D9", 1, 1)]
hinting "bytecode"
size 14
style store_tabs_button_add_remove is navigation_tabs_button:
ysize 35
left_padding 15
right_padding 30
selected_right_padding 30
background Frame(Transform(Image("gui/creamy_pumpkin_pie/book/book_tab.png", oversample=4), matrixcolor=HueMatrix(180.0)), 0, 0, 80, 0, tile=False)
selected_background Frame(Transform(Image("gui/creamy_pumpkin_pie/book/book_tab.png", oversample=4), matrixcolor=HueMatrix(275.0)), 0, 0, 80, 0, tile=False)
insensitive_background Frame(Transform(Image("gui/creamy_pumpkin_pie/book/book_tab.png", oversample=4), matrixcolor=SaturationMatrix(0.0)), 0, 0, 80, 0, tile=False)
activate_sound "sounds/woosh2.ogg"
selected_activate_sound "sounds/woosh.ogg"
style store_tabs_button_add_remove_text is navigation_tabs_button_text:
selected_xoffset 0
style store_checkout_hbox:
fit_first True
spacing 4
xalign 0.5
style store_checkout_vbox:
xalign 0.5
margin (10, 10)
style store_checkout_text is store_text:
size 36
style store_checkbox_button is wardrobe_checkbox_button
style store_checkbox_button_text is wardrobe_checkbox_button_text