WTS/game/scripts/inventory/classes.rpy

237 lines
8.7 KiB
Plaintext
Raw Normal View History

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):
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, use_func=None, use_label=None, give_func=None, give_label=None, limit=100, image="default", givable=False, currency="gold", use_caption=_("Use"), give_caption=_("Give"), owned=0, infinite=False, usable_on=[]):
2022-05-16 23:48:22 +00:00
self.id = id
self.type = type
self.name = name
self.price = price
self.desc = desc
self.unlocked = unlocked
self.use_func = use_func
self.use_label = use_label
self.use_caption = use_caption
self.give_func = give_func
self.give_label = give_label
self.give_caption = give_caption
2022-05-16 23:48:22 +00:00
self.limit = limit
self.image = f"interface/icons/{self.id}.webp" if image == "default" else image
2022-05-16 23:48:22 +00:00
self.currency = currency
self.givable = bool(self.give_func or self.give_label)
self.usable = bool(self.use_func or self.use_label)
2022-05-16 23:48:22 +00:00
self.used = False
self.infinite = infinite
self.usable_on = usable_on
self._owned = owned
2022-05-16 23:48:22 +00:00
inventory.add(self)
2022-05-16 23:48:22 +00:00
def _check_usable(self, func_name):
if not getattr(self, func_name):
raise Exception(f"Item {self.name!r} is not marked as {func_name}able.")
2022-05-16 23:48:22 +00:00
if self.owned == 0:
raise Exception(f"Item {self.name!r} owned count is equal to zero.")
2022-05-16 23:48:22 +00:00
def _use_or_give(self, func_name):
self._check_usable(func_name)
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
func = getattr(self, f"{func_name}_func")
label = getattr(self, f"{func_name}_label")
if func:
func()
if label:
enable_game_menu()
renpy.jump_out_of_context(label) if renpy.context_nesting_level() > 0 else renpy.jump(label)
2022-05-16 23:48:22 +00:00
def use(self):
self._use_or_give("use")
2022-05-16 23:48:22 +00:00
def give(self):
self._use_or_give("give")
2022-05-16 23:48:22 +00:00
def get_image(self):
return self.image() if callable(self.image) else self.image
@property
def caption(self):
return self.use_caption if inventory_mode==0 else self.give_caption # 'inventory_mode' is a global
2022-05-16 23:48:22 +00:00
@property
def owned(self):
return self._owned
@owned.setter
def owned(self, value):
self.unlocked = True
2022-05-16 23:48:22 +00:00
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=id, type=type, name=name, price=price, desc=desc, unlocked=unlocked, limit=1, image=image, givable=False, currency="tokens", use_caption="Apply", owned=owned)
2022-05-16 23:48:22 +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:
raise Exception(f"Decoration {self.name!r} owned count is equal to zero.")
2022-05-16 23:48:22 +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", use_caption=_("Use"), give_caption=_("Give"), owned=0, recipe=None, usable_on=[], levels={}):
super(Potion, self).__init__(id, type=type, name=name, price=price, desc=desc, unlocked=unlocked, give_label=label, limit=limit, image=image, givable=True, currency=currency, use_caption=use_caption, give_caption=give_caption, owned=owned)
2022-05-16 23:48:22 +00:00
# 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}
self.usable = bool(renpy.has_label(f"{self.label}_use"))
2022-05-16 23:48:22 +00:00
if self.recipe is None:
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()):
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
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>"""
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):
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):
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:
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"""
label = f"{self.label}_use"
2022-05-16 23:48:22 +00:00
if not renpy.has_label(label):
raise Exception(f"Potion {self.name!r} has no use label.")
2022-05-16 23:48:22 +00:00
if self.owned == 0:
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]:
raise Exception(f"Potion {self.name!r} is not marked as in progress.")
2022-05-16 23:48:22 +00:00
label = f"{who[:3]}_{self.label}_return"
2022-05-16 23:48:22 +00:00
if not renpy.has_label(label):
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()