diff --git a/game/characters/cho/chibi/stand/0.webp b/game/characters/cho/chibi/stand/0.webp new file mode 100644 index 00000000..c371ccf1 --- /dev/null +++ b/game/characters/cho/chibi/stand/0.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2c6ec1d617cca3fbc225b723b0508eebeacb1f08b2ff222e96c7fff54ceae959 +size 55068 diff --git a/game/characters/cho/chibi/stand/0_bottom_school_skirt_1.webp b/game/characters/cho/chibi/stand/0_bottom_school_skirt_1.webp new file mode 100644 index 00000000..a803a057 --- /dev/null +++ b/game/characters/cho/chibi/stand/0_bottom_school_skirt_1.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a68b683210f8a060548a4abd49dbaed6497917d25f5feee949c9b8a0b632146f +size 10838 diff --git a/game/characters/cho/chibi/stand/0_bra_basic_bra_1.webp b/game/characters/cho/chibi/stand/0_bra_basic_bra_1.webp new file mode 100644 index 00000000..43a7c635 --- /dev/null +++ b/game/characters/cho/chibi/stand/0_bra_basic_bra_1.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:183923d268c2a33233ff8a3be265247ac06af3601df359c02d5cbcb6f094d799 +size 6860 diff --git a/game/characters/cho/chibi/stand/0_panties_basic_panties_1.webp b/game/characters/cho/chibi/stand/0_panties_basic_panties_1.webp new file mode 100644 index 00000000..0b6d637f --- /dev/null +++ b/game/characters/cho/chibi/stand/0_panties_basic_panties_1.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b152dd269de3da1ef6deb4d4fdfd2988bc35f74a4864282b6e37a73a04cd2fd +size 3234 diff --git a/game/characters/cho/chibi/stand/0_shoes_house.webp b/game/characters/cho/chibi/stand/0_shoes_house.webp new file mode 100644 index 00000000..842f54f3 --- /dev/null +++ b/game/characters/cho/chibi/stand/0_shoes_house.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c320fbda915a6df576f4505eefe470670f562578f1434d9888d8250b643b9d21 +size 4196 diff --git a/game/characters/cho/chibi/stand/0_stockings_house.webp b/game/characters/cho/chibi/stand/0_stockings_house.webp new file mode 100644 index 00000000..a7e4e37c --- /dev/null +++ b/game/characters/cho/chibi/stand/0_stockings_house.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:08d88ed2df8d780986897692bc31d3c33175160d487c0b10adfc4083490142d9 +size 15932 diff --git a/game/characters/cho/chibi/stand/0_top_top_school_1.webp b/game/characters/cho/chibi/stand/0_top_top_school_1.webp new file mode 100644 index 00000000..d5722c03 --- /dev/null +++ b/game/characters/cho/chibi/stand/0_top_top_school_1.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:353cae5ae13f2ef4d5b655fb3aac15c94a2b1a03fe7958afd0f07539b516efa4 +size 18626 diff --git a/game/characters/cho/chibi/walk/0.webp b/game/characters/cho/chibi/walk/0.webp new file mode 100644 index 00000000..887cf0bf --- /dev/null +++ b/game/characters/cho/chibi/walk/0.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:24bff78653d56ffe297fe90f28326461730e6e2c6f952df0cec484285c494161 +size 54038 diff --git a/game/characters/cho/chibi/walk/1.webp b/game/characters/cho/chibi/walk/1.webp new file mode 100644 index 00000000..bd527e15 --- /dev/null +++ b/game/characters/cho/chibi/walk/1.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:855a52053bd72d3b2b3802675ed82328edf097d327496a6f0c86b8cb5a94ad0a +size 56228 diff --git a/game/characters/cho/chibi/walk/2.webp b/game/characters/cho/chibi/walk/2.webp new file mode 100644 index 00000000..5f3473d6 --- /dev/null +++ b/game/characters/cho/chibi/walk/2.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e97a1e55e8d6656095fdb2219f9ff14fca492b16a7170460e1a100a63be61e0c +size 59466 diff --git a/game/characters/cho/chibi/walk/3.webp b/game/characters/cho/chibi/walk/3.webp new file mode 100644 index 00000000..0ffc3907 --- /dev/null +++ b/game/characters/cho/chibi/walk/3.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ab6789edadb4ac698f64aca9b1fb26df62b999fcf61e38eacc37fd1cbdd5b63f +size 56848 diff --git a/game/characters/cho/chibi/walk/4.webp b/game/characters/cho/chibi/walk/4.webp new file mode 100644 index 00000000..887cf0bf --- /dev/null +++ b/game/characters/cho/chibi/walk/4.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:24bff78653d56ffe297fe90f28326461730e6e2c6f952df0cec484285c494161 +size 54038 diff --git a/game/characters/cho/chibi/walk/5.webp b/game/characters/cho/chibi/walk/5.webp new file mode 100644 index 00000000..fbad8c46 --- /dev/null +++ b/game/characters/cho/chibi/walk/5.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2c8d345e501fadf7c64a576ca6361ff5c4b2c19d05fd34bb5897accd0e5778e7 +size 54490 diff --git a/game/characters/cho/chibi/walk/6.webp b/game/characters/cho/chibi/walk/6.webp new file mode 100644 index 00000000..fe92aa95 --- /dev/null +++ b/game/characters/cho/chibi/walk/6.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4a1bc51779628526f1fd64940cc0d705bc7661311b3a938bda062d75166413e6 +size 53034 diff --git a/game/characters/cho/chibi/walk/7.webp b/game/characters/cho/chibi/walk/7.webp new file mode 100644 index 00000000..e3c88f0a --- /dev/null +++ b/game/characters/cho/chibi/walk/7.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ed0c8a792391cc4f45183c0a02b52a3a435341507d3abe2dba6714fd0683e067 +size 54178 diff --git a/game/scripts/doll/chibi.rpy b/game/scripts/doll/chibi.rpy index c3db8ca9..dcf00b46 100644 --- a/game/scripts/doll/chibi.rpy +++ b/game/scripts/doll/chibi.rpy @@ -11,6 +11,7 @@ init 5 python: self.name = name self.doll = doll self.pose = pose + self.idle = "stand" self.layer = layer self.zorder = zorder self.zoom = zoom @@ -32,25 +33,62 @@ init 5 python: self.atl_time = 0 self.atl_time_total = 0 self.atl_partial = None + self.atl_looping = False + self.atl_pause = False def anim_constructor(self): """This function is responsible for creating an animation out of raw image files.""" + doll = self.doll path = "characters/{}/chibi/{}/".format(self.name, self.pose) + files = [f for f in renpy.list_files() if f.startswith(path)] images = [] + groups = {} - # Base model - for fn in renpy.list_files(): - if not fn.startswith(path): - continue - + # Construct Animation + for fn in files: basename = os.path.basename(fn) - base, ext = os.path.splitext(basename) + name, ext = os.path.splitext(basename) + d = renpy.displayable(fn) if not ext.lower() in [ ".jpg", ".jpeg", ".png", ".webp" ]: continue - images.append(renpy.displayable(fn)) + if name.isdigit(): + # Create frame group if filename is a frame number and not a child + groups.setdefault(name, {}).setdefault(0, [d]) # Body layer is zorder zero + continue + + # Get frame id, clothing type, and clothing id + frame, ctype, cid = name.split("_", maxsplit=2) + + if not frame in groups: + # Frame group is missing, skip construction + continue + + if (not doll.is_equipped(ctype) or + not doll.is_worn(ctype)): + continue + + equipped = doll.get_equipped(ctype) + zorder = equipped.zorder + + if (not equipped.type == ctype or + not equipped.id == cid): + continue + + groups[frame].setdefault(zorder, [d]) + + # Iterate through frame groups and nested zorder groups + for fgroup in groups.values(): + igroup = [] + + # Sort zorder groups + for zgroup in dict(sorted(fgroup.items())).values(): + # Unpack zorder groups into displayables + igroup.append(Fixed(*zgroup, fit_first=True)) + + images.append(Fixed(*igroup, fit_first=True)) if not images: raise IndexError("Animation Constructor could not find any images inside directory:\n\n\"{}\"".format(path)) @@ -103,8 +141,20 @@ init 5 python: # Determine pose change if show time exceeds animation time. # Looping animations ignore this check because they are rebuilt every loop. - if st > self.atl_time_total: - self.set_pose("stand") + print(ev.type) + + if ((not self.atl_looping and st > self.atl_time_total) + or ev.type == pygame.MOUSEBUTTONUP + or (ev.type == pygame.KEYDOWN and ev.key in [pygame.K_RETURN, pygame.K_SPACE, pygame.K_KP_ENTER, pygame.K_SELECT])): + self.stop() + renpy.restart_interaction() + # else: + # raise renpy.IgnoreEvent + + # def per_interact(self): + # # Handle interrupt events + # if (renpy.is_skipping() or self.atl_pause) and not self.pose == self.idle: + # self.stop() def set_pose(self, pose): if self.pose == pose: @@ -113,14 +163,59 @@ init 5 python: self.pose = pose self.anim_constructor() - def move(self, path, speed=1.0, pause=False, loop=False, warper="linear", at_list=[], pose="walk"): + def set_idle(self, pose): + if self.idle == pose: + return + + self.idle = pose + + def stop(self): + # Freezes the animation + if renpy.in_rollback(): + return + + path, _, _, _ = self.atl_partial.args + pos = path[-1] + xzoom = 1 if (path[-1] > path[-2]) else -1 + zpos = self.zorder + (1.0 / (pos[1] / config.screen_height)) + + self.pos = pos + self.xzoom = xzoom + + self.atl_time = 0 + self.atl_time_total = 0 + + self.set_pose(self.idle) + transform = Transform(pos=pos, zoom=self.zoom, xzoom=xzoom, anchor=(0.5, 1.0)) + image = At(self, transform) # IMPORTANT: Enable perspective and gl_depth for 3D staging + + if not renpy.is_init_phase(): + renpy.show(self.name, at_list=[], layer=self.layer, what=image, zorder=zpos) + + def move(self, path, speed=1.0, pause=True, loop=False, warper="linear", at_list=[], pose="walk", repeat=None, wrap=True, reverse=True): """Makes chibi move""" + + self.atl_looping = loop + self.atl_pause = pause + if isinstance(path, tuple): path = [path] # If 'A' position is not supplied for A -> B movement, use last known position instead. if len(path) < 2: path = [self.pos] + path + # If reverse and loop/repeat is True, and pathing has more than two entries, + # use complex looping by joining the reversed paths + elif reverse and (loop or repeat): + # Reverses the list, strips last entry from the reverse list, and finally joins them. + path += path[1::-1] + + if repeat: + path *= repeat + + if wrap: + # Wrap pathing back to starting position + path.append(path[0]) self.set_pose(pose) @@ -174,6 +269,9 @@ init 5 python: def move_atl(self, path, times, loop, warper, trans, st, at): """Animations are time based, so each segment will happen at a specific frame time.""" + if self.atl_time_total == 0: + return + if loop: timer = st % self.atl_time_total else: @@ -217,7 +315,7 @@ init 5 python: # self.zpos = trans.zpos # TODO: Using zorders is suboptimal and expensive, using 3D staging would be preferable. - zpos = self.zorder + self.pos[1] / config.screen_height + zpos = self.zorder + (1.0 / (self.pos[1] / config.screen_height)) renpy.change_zorder(self.layer, self.name, zpos) return 0 @@ -237,3 +335,16 @@ init 5 python: init offset = 5 default hooch_chibi = DollChibi(name="hooch", doll=hooch) +default cho_chibi_new = DollChibi(name="cho", doll=cho) + +label chibitest: + "Rollback block" + $ renpy.block_rollback() + + "repeat 3" + $ cho_chibi_new.move(path=[(500, 421), (650, 521), (800, 421)], repeat=3) + "loop" + $ cho_chibi_new.move(path=[(500, 421), (650, 521), (800, 421)], loop=True) + "End" + + jump main_room_menu diff --git a/game/scripts/doll/main.rpy b/game/scripts/doll/main.rpy index ab30e88c..8f25d1bf 100644 --- a/game/scripts/doll/main.rpy +++ b/game/scripts/doll/main.rpy @@ -228,7 +228,7 @@ init python: if arg in self.multislots: return any(bool(v[0]) for k, v in self.clothes.items() if k.startswith(arg)) else: - if not self.clothes[arg][0]: + if not self.clothes.get(arg, [None])[0]: return False return True