diff --git a/game/scripts/animations/transforms.rpy b/game/scripts/animations/transforms.rpy index b24abead..2c7c2974 100644 --- a/game/scripts/animations/transforms.rpy +++ b/game/scripts/animations/transforms.rpy @@ -104,12 +104,14 @@ transform main_sprite_position(x, y, flip, scale): transform random_rotation(a=-45, b=45): rotate random.randint(a, b) -transform pulse_hover(t=1.0, strength=0.2, pause=0.0): - animation - linear t matrixcolor BrightnessMatrix(value=strength) - linear t matrixcolor BrightnessMatrix(value=0.0) - pause pause - repeat +transform pulse_hover(t=2.0, strength=0.2, pause=0.0): + matrixcolor BrightnessMatrix(value=0.0) + + on start: + linear t/2 matrixcolor BrightnessMatrix(value=strength) + linear t/2 matrixcolor BrightnessMatrix(value=0.0) + pause pause + repeat transform gui_animation: nearest True diff --git a/game/scripts/characters/tonks/events/hangout.rpy b/game/scripts/characters/tonks/events/hangout.rpy index bf18e31c..b2dea932 100644 --- a/game/scripts/characters/tonks/events/hangout.rpy +++ b/game/scripts/characters/tonks/events/hangout.rpy @@ -150,7 +150,7 @@ label nt_he_firewhisky_E1: ton "A bit more..." ("horny", "base", "angry", "down") ton "That's it, cheers." ("base", "base", "base", "mid") - if nt_he_drink.counter <= 3: # First time only. + if not _event_completed: if game.daytime: gen "Boring lessons ahead?" ("base", xpos="far_left", ypos="head") ton "Not particularly, why?" ("open", "base", "base", "mid") diff --git a/game/scripts/doll/common.rpy b/game/scripts/doll/common.rpy index 23e8e255..12e9cb56 100644 --- a/game/scripts/doll/common.rpy +++ b/game/scripts/doll/common.rpy @@ -55,6 +55,7 @@ init -1 python: _image_cached = False blacklist_toggles = ("hair", "glasses", "pubes", "piercing", "makeup", "tattoo", "earrings") blacklist_unequip = ("hair",) + blacklist_strip = ("pubes", "piercing", "tattoo") multislots = ("makeup", "accessory", "piercing", "tattoo") extensions = {".webp", ".png", ".jxl", ".avif"} sizes = (1010, 1200) # Default sizes used for defining rare cases diff --git a/game/scripts/doll/main.rpy b/game/scripts/doll/main.rpy index 3abc7a0a..7c9380e9 100644 --- a/game/scripts/doll/main.rpy +++ b/game/scripts/doll/main.rpy @@ -281,7 +281,7 @@ init python: def _strip_type(type): for k, v in self.states.items(): - if not k in self.blacklist_unequip and istype(v[0], type): + if istype(v[0], type) and not k in self.blacklist_unequip and (k in self.multislots or not k.startswith(self.blacklist_strip)): v[2] = False def _strip_slot(slot): @@ -299,9 +299,9 @@ init python: if arg == "all": _strip_all() - elif arg == "clothes": + elif arg == "clothes": _strip_type((DollCloth, DollClothDynamic)) - elif arg == "makeup": + elif arg == "makeup": _strip_type(DollMakeup) elif arg == "bodyparts": _strip_type(DollBodypart) diff --git a/game/scripts/doll/makeup.rpy b/game/scripts/doll/makeup.rpy index 2f985ab1..4c613b26 100644 --- a/game/scripts/doll/makeup.rpy +++ b/game/scripts/doll/makeup.rpy @@ -1,9 +1,9 @@ init python: class DollMakeup(DollCloth): - def __init__(self, name, categories, type, id, color, zorder=None, unlocked=False, level=0, blacklist=[], parent=None, modpath=None, tracking=None): + def __init__(self, name, categories, type, id, color, zorder=None, unlocked=False, level=0, blacklist=[], modpath=None, parent=None, tracking=None): self.tracking = tracking - super().__init__(name, categories, type, id, color, zorder, unlocked, level, blacklist, parent, modpath) + super().__init__(name, categories, type, id, color, zorder, unlocked, level, blacklist, modpath, parent) def __repr__(self): return f"DollMakeup(name={self.name}, categories={self.categories}, type={self.type}, id={self.id}, color={self.color}, zorder={self.zorder}, unlocked={self.unlocked}, level={self.level}, blacklist={self.blacklist}, parent={self.parent}, modpath={self.modpath or None}, tracking={self.tracking})" @@ -59,3 +59,7 @@ init python: layers.setdefault(ltype, [f, zorder]) return layers + + def clone(self): + """Creates a clone of this cloth object. Since it requires a parent object it should be used internally only to avoid object depth issue.""" + return DollMakeup(self.name, self.categories, self.type, self.id, [x for x in self.color] if self.color else None, self.zorder, self.unlocked, self.level, self.blacklist, self.modpath, self, self.tracking) \ No newline at end of file diff --git a/game/scripts/options.rpy b/game/scripts/options.rpy index 069b4779..146577bd 100644 --- a/game/scripts/options.rpy +++ b/game/scripts/options.rpy @@ -37,7 +37,7 @@ define config.debug = config.developer or prerelease define config.console = True # Game version and naming -define config.version = "1.45.1" +define config.version = "1.45.2" define compatible_version = 1.451 define config.name = "Witch Trainer Silver" diff --git a/game/scripts/rooms/init.rpy b/game/scripts/rooms/init.rpy index 3fcc9d7d..732332a8 100644 --- a/game/scripts/rooms/init.rpy +++ b/game/scripts/rooms/init.rpy @@ -39,11 +39,22 @@ init -1 python: # Backwards compatibility, to be resolved if possible. 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, + self.action, self.hovered, self.unhovered, self.tooltip, self.decoration, self.zorder, self.hidden] + ) + + return hash(salt) + def set_image(self, idle, hover=None): self.idle = idle self.hover = hover or idle def get_idle(self): + return self._get_idle(self.generate_hash()) + + @functools.cache + def _get_idle(self, hash): if self.hidden: return Null() @@ -55,6 +66,10 @@ init -1 python: return Fixed(self.idle, fit_first=True) def get_hover(self): + return self._get_hover(self.generate_hash()) + + @functools.cache + def _get_hover(self, hash): if self.hidden: return Null() diff --git a/game/scripts/utility/updater.rpy b/game/scripts/utility/updater.rpy index dec0e805..777525f3 100644 --- a/game/scripts/utility/updater.rpy +++ b/game/scripts/utility/updater.rpy @@ -75,8 +75,19 @@ init python: # For unknown reasons, sometimes version is missing from the save, so we need a fallback current = getattr(renpy.store, "version", latest) - # if current <= 1.431: - # # code + if current < 1.452: + + # Fix makeup object types inside saved outfits + for i in states.dolls: + doll = getattr(store, i) + + for j in doll.outfits: + if j.has_type("makeup"): + + objects = [x.parent.clone() for x in j.group] + + j.group = objects + j.is_stale() if current > latest: raise Exception("Loaded save file is incompatible. (Save Version: {}, Game Version: {})".format(current, latest))