diff --git a/game/scripts/interface/wheelmenu.rpy b/game/scripts/interface/wheelmenu.rpy new file mode 100644 index 00000000..597da164 --- /dev/null +++ b/game/scripts/interface/wheelmenu.rpy @@ -0,0 +1,120 @@ +init python in wheelmenu: + import math + + def pos(num_buttons): + reference_num_buttons = 32 + reference_radius = 0.5 + radius = reference_radius * (num_buttons / reference_num_buttons) ** 0.5 + angle_step = 2 * math.pi / num_buttons + start_angle = angle_step / 2 if num_buttons % 2 else 0 + positions = [(min(max(0.5 + math.cos(start_angle + i * angle_step) * radius, 0.0), 1.0), + min(max(0.5 + math.sin(start_angle + i * angle_step) * radius, 0.0), 1.0)) + for i in range(num_buttons)] + return positions + + def button(displayable, action, condition, state=None, **kwargs): + """ + displayable - Ren'Py displayable + action - Ren'Py screen action + condition - Boolean + state - + None - No change + "hidden" - Hidden if condition==False + "disabled" - Disabled if condition==False + """ + + if state == "hidden": + return None + elif state == "disabled": + return renpy.store.Button(displayable, action=action, style_prefix="wheelmenu_disabled", **kwargs) + + if condition: + return renpy.store.Button(displayable, action=action, style_prefix="wheelmenu", **kwargs) + else: + return None + +init python: + def create_wheelmenu(elements): + # Proxy function; We cannot evaluate in a named store without side effects. + + buttons = [] + for name, (displayable, action, condition) in elements.items(): + condition = eval(condition) + + buttons.append(wheelmenu.button(displayable, action, condition, tooltip=name)) + + positions = wheelmenu.pos(len(buttons)) + + return tuple(zip(buttons, positions)) # Nonhashable types cannot be used in a screen, so we use a tuple instead. + +label wheelmenu(btns, ret, pos=None): + call screen wheelmenu(btns, pos) + + jump expression ret + +screen wheelmenu(btns, pos): + layer "interface" + tag wheelmenu + zorder 4 + style_prefix "wheelmenu" + + default start_pos = pos or renpy.get_mouse_pos() + + use close_button_background + + window: + id "wheelmenu" + pos start_pos + + for btn, pos in btns: + add btn pos pos + + # TODO: Add genie's eyes/face following mouse. + +style wheelmenu_window is empty: + maximum (400, 400) + anchor (0.5, 0.5) + +style wheelmenu_window_button is empty: + background "#ffffffc0" + xysize (48, 48) + anchor (0.5, 0.5) + +style wheelmenu_disabled_window_button is wheelmenu_window_button: + background "#ffffff80" + +style wheelmenu_window_text is default: + anchor (0.5, 0.5) + color "#fff" + size 10 + outlines [(1, "#00000080", 1, 0)] + +style wheelmenu_button_text is wheelmenu_text + +# transform tooltip_follow: +# events False +# function tooltip_func + +# init python: + + # def tooltip_func(trans, st, at): + # x, y = renpy.get_mouse_pos() + + # if trans.pos is not (x, y): + # cw, ch = trans.child.window_size + + # xanchor = 1.0 if (x + int(cw)) > (config.screen_width) else 0.0 + # yanchor = 1.0 if (y + int(ch)) > (config.screen_height) else 0.0 + + # xoffset = 18 if xanchor else 0 + # yoffset = 24 if yanchor else 0 + # trans.pos = (x, y) + # trans.anchor = (xanchor, yanchor) + # trans.offset = (xoffset, yoffset) + + # return 0 + + # if not renpy.android: + + # config.always_shown_screens.append("tooltip") + # config.per_frame_screens.append("tooltip") diff --git a/game/scripts/rooms/init.rpy b/game/scripts/rooms/init.rpy index 732332a8..e7b8eab2 100644 --- a/game/scripts/rooms/init.rpy +++ b/game/scripts/rooms/init.rpy @@ -2,8 +2,9 @@ init -1 python: class Room(object): - def __init__(self, id): + def __init__(self, id, menu=None): self.id = id + self.menu = menu self.objects = set() def add(self, obj): @@ -40,7 +41,7 @@ init -1 python: self.xpos, self.ypos = self.pos def generate_hash(self): - salt = str( [self.id, self.pos, self.idle, self.hover, self.foreground, self.background, self.anchor, self.focus_mask, + salt = str( [self.id, self.pos, self.idle, self.hover, self.foreground, self.background, self.anchor, self.focus_mask, self.action, self.hovered, self.unhovered, self.tooltip, self.decoration, self.zorder, self.hidden] ) @@ -95,9 +96,18 @@ init -1 python: deco = self.decoration if deco and deco.replace_action: - return deco.replace_action + action = deco.replace_action + else: + action = self.action - return self.action + if isinstance(action, dict): + if not action: + raise IndexError(f"Action dict was provided for '{self.id}' but it is empty.") + + btns = create_wheelmenu(action) + return Call("wheelmenu", btns=btns, ret=self.room.menu) + + return action def get_anchor(self): deco = self.decoration diff --git a/game/scripts/rooms/main_room/init.rpy b/game/scripts/rooms/main_room/init.rpy index d293bf00..afe034f7 100644 --- a/game/scripts/rooms/main_room/init.rpy +++ b/game/scripts/rooms/main_room/init.rpy @@ -1,12 +1,46 @@ -default main_room = Room("main_room") +default main_room = Room("main_room", "main_room_menu") default fireplace_OBJ = RoomObject(main_room, "fireplace", pos=(693, 277), idle="fireplace_idle_shadow", focus_mask="fireplace_hover", foreground=None, action=Jump("fireplace"), tooltip="Light/Extinguish") default cupboard_OBJ = RoomObject(main_room, "cupboard", pos=(260, 280), idle="cupboard_idle", action=Jump("cupboard"), tooltip="Rummage") -default phoenix_OBJ = RoomObject(main_room, "phoenix", pos=(557, 272), idle="phoenix_idle", hover="phoenix_hover", focus_mask="phoenix_idle", background="phoenix_feather", action=Jump("phoenix"), tooltip="Interact") -default door_OBJ = RoomObject(main_room, "door", pos=(898, 315), idle="door_idle", focus_mask="door_hover", action=Jump("door"), tooltip="Summon") +default phoenix_OBJ = RoomObject( + main_room, "phoenix", + pos=(557, 272), + idle="phoenix_idle", + hover="phoenix_hover", + focus_mask="phoenix_idle", + background="phoenix_feather", + action={ + "Feed": (Text("Feed"), Jump("phoenix_feed"), "True"), + "Pet": (Text("Pet"), Jump("phoenix_pet"), "True") + }, + tooltip="Phoenix" +) +default door_OBJ = RoomObject(main_room, "door", pos=(898, 315), idle="door_idle", focus_mask="door_hover", action=Jump("door"), tooltip="Door") default candleL_OBJ = RoomObject(main_room, "candle_left", pos=(350, 160), idle="candle_left", foreground=None, action=ToggleVariable("candleL_OBJ.foreground", "candle_fire", None), zorder=3) default candleR_OBJ = RoomObject(main_room, "candle_right", pos=(833, 225), idle="candle_right", foreground=None, action=ToggleVariable("candleR_OBJ.foreground", "candle_fire", None), zorder=3) -default desk_OBJ = RoomObject(main_room, "desk", pos=(370, 336), idle="ch_gen sit_behind_desk", hover="ch_gen sit_behind_desk_hover", focus_mask="ch_gen sit_behind_desk", action=Jump("desk"), hovered=Show("gui_tooltip", img="emo_exclaim", xx=335, yy=210), unhovered=Hide("gui_tooltip"), tooltip="Desk", zorder=1) +default desk_OBJ = RoomObject( + main_room, "desk", + pos=(370, 336), + idle="ch_gen sit_behind_desk", + hover="ch_gen sit_behind_desk_hover", + focus_mask="ch_gen sit_behind_desk", + action={ + "Sleep": (Text("Slee"), If(game.daytime, Return("night_start"), Return("day_start")), "True"), + "Jerk Off": (Text("Jerk"), Jump("jerk_off"), "True"), + "Do Paperwork": (Text("Work"), Jump("paperwork"), "True"), + "Open Inventory": (Text("Inve"), Jump("inventory"), "True"), + "Open Deck Builder": (Text("Deck"), Jump("deck_builder"), "states.cardgame.unlocked"), + }, + hovered=Show( + "gui_tooltip", + img="emo_exclaim", + xx=335, + yy=210 + ), + unhovered=Hide("gui_tooltip"), + tooltip="Desk", + zorder=1 +) default poster_OBJ = RoomObject(main_room, "poster", pos=(364, 285), idle=Null(127, 166), action=Jump("enlarge_poster"), zorder=-1) default trophy_OBJ = RoomObject(main_room, "trophy", pos=(650, 120), idle=Null(), action=None, zorder=-1) default chair_OBJ = RoomObject(main_room, "chair", pos=(793, 300), idle="chair_right", action=None, zorder=0) diff --git a/game/scripts/rooms/main_room/objects/phoenix.rpy b/game/scripts/rooms/main_room/objects/phoenix.rpy index 7a1bdd69..f7145c00 100644 --- a/game/scripts/rooms/main_room/objects/phoenix.rpy +++ b/game/scripts/rooms/main_room/objects/phoenix.rpy @@ -15,9 +15,10 @@ label phoenix: if states.gen.ev.intro.bird_examined and states.gen.ev.intro.desk_examined and states.gen.ev.intro.cupboard_examined and states.gen.ev.intro.door_examined and states.gen.ev.intro.fireplace_examined: jump genie_intro_E2 - else: - jump main_room_menu + jump main_room_menu + +label phoenix_feed: if not states.bird_fed: $ states.bird_fed = True $ states.bird_fed_times += 1 @@ -32,11 +33,25 @@ label phoenix: random: gen "There you go..." ("base", xpos="far_left", ypos="head") gen "Eat up, buddy." ("base", xpos="far_left", ypos="head") - pause .8 + gen "Savour every bite, bird." ("base", xpos="far_left", ypos="head") + gen "Don't be shy—dig in, it's not like this stuff grows on trees." ("base", xpos="far_left", ypos="head") + gen "Eat up! You're the star ingredient in an upcoming hearty phoenix soup." ("grin", xpos="far_left", ypos="head") + pause .8 call gen_chibi("sit_behind_desk") - jump main_room_menu + else: + random: + gen "I already fed it today." ("base", xpos="far_left", ypos="head") + gen "The poor thing doesn't even need more food today, it's all set." ("base", xpos="far_left", ypos="head") + gen "Let's leave the Phoenix to its nap. It had enough for the day." ("base", xpos="far_left", ypos="head") + gen "This phoenix prefers to take things slow and steady." ("base", xpos="far_left", ypos="head") + gen "It's full up and won't need to eat till tomorrow." ("base", xpos="far_left", ypos="head") + gen "I wonder if I pet you enough, would you magically transform into a sexy woman?" ("base", xpos="far_left", ypos="head") + pause .8 + jump main_room_menu + +label phoenix_pet: if not states.bird_petted: $ states.bird_petted = True $ states.bird_petted_times += 1 @@ -46,14 +61,72 @@ label phoenix: random: gen "Who's a good bird?" ("base", xpos="far_left", ypos="head") - "*Pat *Pat *Pat..." - "Glad you aren't as noisy as Iago..." - pause 2.4 + "*Pat* *Pat* *Pat*..." + gen "Glad you aren't as noisy as Iago..." ("base", xpos="far_left", ypos="head") + gen "Can't resist a little head scratch, eh?" ("base", xpos="far_left", ypos="head") + gen "Nice feathers, wouldn't want to pluck those out..." ("base", xpos="far_left", ypos="head") + gen "See? I scratch your back, you scratch mine." ("base", xpos="far_left", ypos="head") + block if 20 > states.bird_petted_times > 10: + gen "I've petted you {number=states.bird_petted_times} times. Just a couple more, and I'm sure something will happen... Right?" ("base", xpos="far_left", ypos="head") + block if 30 > states.bird_petted_times > 20: + gen "How many more times do I have to pet you for you to do something? It's been {number=states.bird_petted_times} already!" ("angry", xpos="far_left", ypos="head") + block if 40 > states.bird_petted_times > 30: + gen "Dear diary, it's been {number=states.bird_petted_times} pets since I landed here, yet that stubborn bird still refuses to talk to me." ("base", xpos="far_left", ypos="head") + block if 50 > states.bird_petted_times > 40: + gen "I pet you patiently, but all I get is silence. Wait, how many times was it again? {number=states.bird_petted_times}?" ("base", xpos="far_left", ypos="head") + block if 60 > states.bird_petted_times > 50: + gen "I've read about talking birds, but you must have missed that chapter." ("base", xpos="far_left", ypos="head") + block if 70 > states.bird_petted_times > 60: + gen "Why won't you even acknowledge my presence, bird?" ("base", xpos="far_left", ypos="head") + block if 80 > states.bird_petted_times > 70: + gen "Another day, another attempt to coax some words out of you." ("base", xpos="far_left", ypos="head") + block if 90 > states.bird_petted_times > 80: + gen "Do you understand how hard it is to communicate with a bird that won't talk back?" ("base", xpos="far_left", ypos="head") + block if 100 > states.bird_petted_times > 90: + gen "I'm starting to wonder if you're just ignoring me on purpose." ("base", xpos="far_left", ypos="head") + block if 110 > states.bird_petted_times > 100: + gen "This is getting old. Can't you just say something already?" ("base", xpos="far_left", ypos="head") + block if 120 > states.bird_petted_times > 110: + gen "I've tried everything. What's it going to take to get through to you?" ("base", xpos="far_left", ypos="head") + block if 130 > states.bird_petted_times > 120: + gen "You're testing my patience, feathered friend." ("base", xpos="far_left", ypos="head") + block if 140 > states.bird_petted_times > 130: + gen "It's like talking to a brick wall, but at least a brick wall doesn't pretend to understand." ("base", xpos="far_left", ypos="head") + block if 150 > states.bird_petted_times > 140: + gen "Congratulations, you've mastered the art of infuriating silence." ("base", xpos="far_left", ypos="head") + faw "..." + block if 300 > states.bird_petted_times > 200: + gen "Hello darkness my old friend..." ("base", xpos="far_left", ypos="head") + faw "*cawk*" + gen "There's no way that fucking worked!" ("angry", xpos="far_left", ypos="head") + gen "Seriously, though, can you talk now?" ("base", xpos="far_left", ypos="head") + faw "..." + gen "... Just great." ("base", xpos="far_left", ypos="head") + block if states.bird_petted_times > 300: + gen "I can't believe I'm still doing this." ("base", xpos="far_left", ypos="head") + faw "AHHHH AFTER TEN THOUSAND YEARS I'M FREE!" + gen "BY THE GREAT DESERT SANDS, IT FINALLY WORKED!" ("grin", xpos="far_left", ypos="head") + gen "But wait, I've only been doing this for {number=game.day}..." ("base", xpos="far_left", ypos="head") + faw "Oh, really? Well, I still have time for a nap then." + gen "WAIT A FUCKING—" ("angry", xpos="far_left", ypos="head") + + call gen_chibi("sit_behind_desk") + with blackfade + + gen "Ugh... I guess I must have fell asleep at some point..." ("base", xpos="far_left", ypos="head") + gen "Was it all but a dream?" ("base", xpos="far_left", ypos="head") + + jump main_room_menu + + pause .8 call gen_chibi("sit_behind_desk") - jump main_room_menu - - gen "I have already fed and petted it today." ("base", xpos="far_left", ypos="head") - gen "Wouldn't want to overdo it." ("base", xpos="far_left", ypos="head") + else: + random: + gen "This phoenix has reached its daily petting limit, sadly, I'm afraid." ("base", xpos="far_left", ypos="head") + gen "I have already petted it today." ("base", xpos="far_left", ypos="head") + gen "It's in a post-pet state, I should leave it alone." ("base", xpos="far_left", ypos="head") + gen "I don't want to cause carpel-talon tunnel." ("base", xpos="far_left", ypos="head") + gen "Gave that bird a good ruffling, now off to groom a griffin." ("base", xpos="far_left", ypos="head") jump main_room_menu