2022-05-16 23:48:22 +00:00
|
|
|
init python:
|
|
|
|
class Inventory(object):
|
|
|
|
def __init__(self):
|
|
|
|
self.items = set()
|
|
|
|
|
|
|
|
def add(self, item):
|
|
|
|
self.items.add(item)
|
|
|
|
|
|
|
|
def remove(self, item):
|
|
|
|
self.items.remove(item)
|
|
|
|
|
|
|
|
def get_instances(self):
|
|
|
|
return self.items
|
|
|
|
|
|
|
|
def get_instances_of_type(self, type):
|
2024-08-07 17:37:07 +00:00
|
|
|
return sorted([x for x in self.get_instances() if x.type == type], key=lambda y: natsort_key(y.name))
|
2022-05-16 23:48:22 +00:00
|
|
|
|
|
|
|
class Item(object):
|
|
|
|
def __init__(self, id, type, name, price=0, desc="", unlocked=True, func=None, label=None, limit=100, image="default", givable=False, currency="gold", caption="use", owned=0, infinite=False, give_label=None, usable_on=[]):
|
|
|
|
self.id = id
|
|
|
|
self.type = type
|
|
|
|
self.name = name
|
|
|
|
self.price = price
|
|
|
|
self.desc = desc
|
|
|
|
self.unlocked = unlocked
|
|
|
|
self.func = func
|
|
|
|
self.label = label
|
|
|
|
self.limit = limit
|
2024-03-26 19:31:41 +00:00
|
|
|
if image == "default":
|
|
|
|
image = f"interface/icons/{self.id}.webp"
|
|
|
|
self.image = image
|
2022-05-16 23:48:22 +00:00
|
|
|
self.currency = currency
|
|
|
|
self.caption = caption
|
|
|
|
|
|
|
|
self.givable = givable
|
|
|
|
self.usable = bool(self.func or self.label)
|
|
|
|
self.used = False
|
|
|
|
self._owned = owned
|
|
|
|
self.infinite = infinite
|
|
|
|
self.give_label = give_label
|
|
|
|
self.usable_on = usable_on
|
|
|
|
|
|
|
|
inventory.add(self)
|
|
|
|
|
|
|
|
def use(self):
|
|
|
|
if not self.usable:
|
2024-03-26 19:31:41 +00:00
|
|
|
raise Exception(f"Item {self.name!r} is not usable as it does not have any function or a label.")
|
2022-05-16 23:48:22 +00:00
|
|
|
|
|
|
|
if self.owned == 0:
|
2024-03-26 19:31:41 +00:00
|
|
|
raise Exception(f"Item {self.name!r} owned count is equal to zero.")
|
2022-05-16 23:48:22 +00:00
|
|
|
|
|
|
|
if not self.type == "quest":
|
|
|
|
# Quest items require manual triggers, it's more convenient.
|
|
|
|
self.used = True
|
|
|
|
|
|
|
|
if self.func:
|
|
|
|
self.func()
|
|
|
|
|
|
|
|
if self.label:
|
|
|
|
if renpy.context_nesting_level() > 0:
|
|
|
|
renpy.jump_out_of_context(self.label)
|
|
|
|
else:
|
|
|
|
renpy.jump(self.label)
|
|
|
|
|
|
|
|
def give(self, who):
|
|
|
|
if not self.givable:
|
2024-03-26 19:31:41 +00:00
|
|
|
raise Exception(f"Item {self.name!r} is not marked as givable.")
|
2022-05-16 23:48:22 +00:00
|
|
|
|
|
|
|
if self.owned == 0:
|
2024-03-26 19:31:41 +00:00
|
|
|
raise Exception(f"Item {self.name!r} owned count is equal to zero.")
|
2022-05-16 23:48:22 +00:00
|
|
|
|
|
|
|
if not self.type == "quest":
|
|
|
|
# Quest items require manual triggers, it's more convenient.
|
|
|
|
self.used = True
|
|
|
|
|
|
|
|
if self.func:
|
|
|
|
self.func()
|
|
|
|
|
|
|
|
if self.give_label:
|
|
|
|
if renpy.context_nesting_level() > 0:
|
|
|
|
renpy.jump_out_of_context(self.give_label)
|
|
|
|
else:
|
|
|
|
renpy.jump(self.give_label)
|
|
|
|
|
|
|
|
def get_image(self):
|
2022-09-29 21:19:55 +00:00
|
|
|
if isinstance(self.image, str):
|
2022-05-16 23:48:22 +00:00
|
|
|
return self.image
|
|
|
|
else:
|
|
|
|
return self.image()
|
|
|
|
|
|
|
|
@property
|
|
|
|
def owned(self):
|
|
|
|
return self._owned
|
|
|
|
|
|
|
|
@owned.setter
|
|
|
|
def owned(self, value):
|
|
|
|
if not self.unlocked:
|
|
|
|
self.unlocked = True
|
|
|
|
|
|
|
|
self._owned = max(min(value, self.limit), 0)
|
|
|
|
|
|
|
|
class Decoration(Item):
|
|
|
|
room_scale = 0.5
|
|
|
|
|
|
|
|
def __init__(self, id, type, name, placement, price=0, desc="", unlocked=True, image="default", room_image="default", room_image_hover=None, owned=0, replaces=False, use_action=None, replace_action=None, replace_anchor=None, replace_pos=None):
|
|
|
|
super(Decoration, self).__init__(id, type, name, price, desc, unlocked, None, None, 1, image, False, "tokens", "Apply", owned)
|
|
|
|
|
2024-03-26 19:31:41 +00:00
|
|
|
if room_image == "default":
|
|
|
|
room_image = f"images/rooms/main_room/decorations/{self.id}.webp"
|
|
|
|
self.room_image = Transform(room_image, zoom=self.room_scale)
|
|
|
|
self.room_image_hover = Transform(room_image_hover or room_image, zoom=self.room_scale)
|
2022-05-16 23:48:22 +00:00
|
|
|
self.usable = True
|
|
|
|
self.placement = placement
|
|
|
|
self.in_use = False
|
|
|
|
self.replaces = replaces
|
|
|
|
self.use_action = use_action
|
|
|
|
self.replace_action = replace_action
|
|
|
|
self.replace_anchor = replace_anchor
|
|
|
|
self.replace_pos = replace_pos
|
|
|
|
|
|
|
|
if not isinstance(self.placement, RoomObject):
|
|
|
|
raise TypeError("Placement must be a RoomObject instance reference.")
|
|
|
|
|
|
|
|
def use(self):
|
|
|
|
if self.owned == 0:
|
2024-03-26 19:31:41 +00:00
|
|
|
raise Exception(f"Decoration {self.name!r} owned count is equal to zero.")
|
2022-05-16 23:48:22 +00:00
|
|
|
|
2023-03-15 22:27:08 +00:00
|
|
|
achievements.unlock("decorator")
|
|
|
|
|
2022-05-16 23:48:22 +00:00
|
|
|
target = self.placement
|
|
|
|
|
|
|
|
if not target.decoration is None:
|
|
|
|
target.decoration.in_use = False
|
|
|
|
|
|
|
|
if self.use_action:
|
|
|
|
self.use_action()
|
|
|
|
|
|
|
|
# Toggle
|
|
|
|
if not target.decoration == self:
|
|
|
|
target.set_decoration(self)
|
|
|
|
self.in_use = True
|
|
|
|
else:
|
|
|
|
target.set_decoration(None)
|
|
|
|
self.in_use = False
|
|
|
|
|
|
|
|
class Potion(Item):
|
|
|
|
def __init__(self, id, type, name, price=0, desc="", unlocked=True, label=None, limit=100, image="default", currency="gold", caption="give", owned=0, recipe=None, usable_on=[], levels={}):
|
|
|
|
super(Potion, self).__init__(id, type, name, price, desc, unlocked, None, label, limit, image, True, currency, caption, owned)
|
|
|
|
|
|
|
|
# self.givable = bool(self.give_label)
|
|
|
|
self.label = label
|
|
|
|
self.recipe = recipe
|
|
|
|
self.usable_on = usable_on
|
|
|
|
self.levels = levels
|
|
|
|
|
|
|
|
self.make_intro = False
|
|
|
|
self.in_progress = {i: False for i in usable_on}
|
|
|
|
|
2024-03-26 19:31:41 +00:00
|
|
|
self.usable = bool(renpy.has_label(f"{self.label}_use"))
|
2022-05-16 23:48:22 +00:00
|
|
|
|
|
|
|
if self.recipe is None:
|
2024-03-26 19:31:41 +00:00
|
|
|
raise Exception(f"Potion {self.name!r} recipe is empty!")
|
2022-05-16 23:48:22 +00:00
|
|
|
|
|
|
|
def has_ingredients(self):
|
|
|
|
return all(x.owned > 0 for x in self.recipe)
|
|
|
|
|
|
|
|
def set_active(self, who):
|
|
|
|
"""Marks the event as 'in progress' and will trigger a return event in the morning/evening."""
|
2022-09-29 21:19:55 +00:00
|
|
|
if not who in list(self.in_progress.keys()):
|
2024-03-26 19:31:41 +00:00
|
|
|
raise Exception(f"Potion {self.name!r} is not marked as usable on {who!r}.")
|
2022-05-16 23:48:22 +00:00
|
|
|
|
|
|
|
self.in_progress[who] = True
|
|
|
|
|
|
|
|
def make(self):
|
|
|
|
if not self.has_ingredients():
|
|
|
|
return
|
|
|
|
|
|
|
|
for i in self.recipe:
|
|
|
|
if not i.infinite:
|
|
|
|
i.owned -= 1
|
|
|
|
|
|
|
|
self.owned += 1
|
2024-03-26 19:31:41 +00:00
|
|
|
label = f"{self.label}_make"
|
2022-05-16 23:48:22 +00:00
|
|
|
|
|
|
|
if renpy.has_label(label) and not self.make_intro:
|
|
|
|
self.make_intro = True
|
|
|
|
self.jump(label)
|
|
|
|
|
|
|
|
def check_progression(self, who):
|
|
|
|
"""Check if progression is eligible to play this event"""
|
|
|
|
progression = get_character_progression(who)
|
|
|
|
|
|
|
|
return (progression >= self.levels.get(who))
|
|
|
|
|
|
|
|
def give(self, who):
|
|
|
|
"""Use potion on <active_girl>"""
|
|
|
|
|
2024-03-26 19:31:41 +00:00
|
|
|
give_label = f"{who[:3]}_{self.label}_give"
|
|
|
|
check_label = f"{who[:3]}_potion_check"
|
2022-05-16 23:48:22 +00:00
|
|
|
|
|
|
|
if not renpy.has_label(give_label):
|
2024-03-26 19:31:41 +00:00
|
|
|
raise Exception(f"Potion {self.name!r} give label doesn't exist.")
|
2022-05-16 23:48:22 +00:00
|
|
|
|
|
|
|
if not renpy.has_label(check_label):
|
2024-03-26 19:31:41 +00:00
|
|
|
raise Exception(f"Potion {self.name!r} check label doesn't exist for {who!r}.")
|
2022-05-16 23:48:22 +00:00
|
|
|
|
|
|
|
if self.owned == 0:
|
2024-03-26 19:31:41 +00:00
|
|
|
raise Exception(f"Potion {self.name!r} owned count is equal to zero.")
|
2022-05-16 23:48:22 +00:00
|
|
|
|
|
|
|
if not self.check_progression(who):
|
|
|
|
self.jump(check_label)
|
|
|
|
|
|
|
|
self.owned -= 1
|
|
|
|
self.jump(give_label)
|
|
|
|
|
|
|
|
def use(self):
|
|
|
|
"""Use potion on Genie"""
|
|
|
|
|
2024-03-26 19:31:41 +00:00
|
|
|
label = f"{self.label}_use"
|
2022-05-16 23:48:22 +00:00
|
|
|
|
|
|
|
if not renpy.has_label(label):
|
2024-03-26 19:31:41 +00:00
|
|
|
raise Exception(f"Potion {self.name!r} has no use label.")
|
2022-05-16 23:48:22 +00:00
|
|
|
|
|
|
|
if self.owned == 0:
|
2024-03-26 19:31:41 +00:00
|
|
|
raise Exception(f"Potion {self.name!r} owned count is equal to zero.")
|
2022-05-16 23:48:22 +00:00
|
|
|
|
|
|
|
self.owned -= 1
|
|
|
|
self.jump(label)
|
|
|
|
|
|
|
|
def ret(self, who):
|
|
|
|
"""Play the return event for <girl>"""
|
|
|
|
|
|
|
|
if not self.in_progress[who]:
|
2024-03-26 19:31:41 +00:00
|
|
|
raise Exception(f"Potion {self.name!r} is not marked as in progress.")
|
2022-05-16 23:48:22 +00:00
|
|
|
|
2024-03-26 19:31:41 +00:00
|
|
|
label = f"{who[:3]}_{self.label}_return"
|
2022-05-16 23:48:22 +00:00
|
|
|
|
|
|
|
if not renpy.has_label(label):
|
2024-03-26 19:31:41 +00:00
|
|
|
raise Exception(f"Potion {self.name!r} has no return label.")
|
2022-05-16 23:48:22 +00:00
|
|
|
|
|
|
|
self.in_progress[who] = False
|
|
|
|
self.jump(label)
|
|
|
|
|
|
|
|
def jump(self, label):
|
|
|
|
if renpy.context_nesting_level() > 0:
|
|
|
|
renpy.jump_out_of_context(label)
|
|
|
|
else:
|
|
|
|
renpy.jump(label)
|
|
|
|
|
|
|
|
init offset = -5
|
|
|
|
|
|
|
|
default inventory = Inventory()
|