Mod Ren'Py Being a DIK Walkthrough+Cheat Mod [v0.10.1][scrappy]

4.70 star(s) 31 Votes

Hotkillerz

Member
May 1, 2017
379
212
Wrathbuu Hotkillerz

Try this
Code:
            # Copyright 2004-2019 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

# This file contains code that handles the execution of python code
# contained within the script file. It also handles rolling back the
# game state to some time in the past.

from __future__ import print_function

# Import the python ast module, not ours.
ast = __import__("ast", { })

# Import the future module itself.
import __future__

import marshal
import random
import weakref
import re
import sys
import time

import renpy.audio

##############################################################################
# Code that implements the store.

# Deleted is a singleton object that's used to represent an object that has
# been deleted from the store.


class StoreDeleted(object):

    def __reduce__(self):
        return "deleted"


deleted = StoreDeleted()


class StoreModule(object):
    """
    This class represents one of the modules containing the store of data.
    """

    # Set our dict to be the StoreDict. Then proxy over setattr and delattr,
    # since Python won't call them by default.

    def __reduce__(self):
        return (get_store_module, (self.__name__,))

    def __init__(self, d):
        object.__setattr__(self, "__dict__", d)

    def __setattr__(self, key, value):
        self.__dict__[key] = value

    def __delattr__(self, key):
        del self.__dict__[key]

# Used to unpickle a store module.


def get_store_module(name):
    return sys.modules[name]


from renpy.pydict import DictItems, find_changes

EMPTY_DICT = { }
EMPTY_SET = set()


class StoreDict(dict):
    """
    This class represents the dictionary of a store module. It logs
sets and deletes.
    """

    def __reduce__(self):
        raise Exception("Cannot pickle a reference to a store dictionary.")

    def __init__(self):

        # The value of this dictionary at the start of the current
        # rollback period (when begin() was last called).
        self.old = DictItems(self)

        # The set of variables in this StoreDict that changed since the
        # end of the init phase.
        self.ever_been_changed = set()

    def reset(self):
        """
        Called to reset this to its initial conditions.
        """

        self.ever_been_changed = set()
        self.clear()
        self.old = DictItems(self)

    def begin(self):
        """
        Called to mark the start of a rollback period.
        """

        self.old = DictItems(self)

    def get_changes(self, cycle):
        """
        For every key that has changed since begin() was called, returns a
dictionary mapping the key to its value when begin was called, or
deleted if it did not exist when begin was called.

As a side-effect, updates self.ever_been_changed, and returns the
changes to ever_been_changed as well.

`cycle`
If true, this cycles the old changes to the new changes. If
False, does not.
        """

        new = DictItems(self)
        rv = find_changes(self.old, new, deleted)

        if cycle:
            self.old = new

        if rv is None:
            return EMPTY_DICT, EMPTY_SET

        delta_ebc = set()

        if cycle:

            for k in rv:
                if k not in self.ever_been_changed:
                    self.ever_been_changed.add(k)
                    delta_ebc.add(k)

        return rv, delta_ebc


def begin_stores():
    """
    Calls .begin on every store dict.
    """

    for sd in store_dicts.itervalues():
        sd.begin()


# A map from the name of a store dict to the corresponding StoreDict object.
# This isn't reset during a reload, so store objects stay the same in modules.
store_dicts = { }

# Same, for module objects.
store_modules = { }

# The store dicts that have been cleared and initialized during the current
# run.
initialized_store_dicts = set()


def create_store(name):
    """
    Creates the store with `name`.
    """

    parent, _, var = name.rpartition('.')

    if parent:
        create_store(parent)

    name = str(name)

    if name in initialized_store_dicts:
        return

    initialized_store_dicts.add(name)

    # Create the dict.
    d = store_dicts.setdefault(name, StoreDict())
    d.reset()

    # Set the name.
    d["__name__"] = name
    d["__package__"] = name

    # Set up the default contents of the store.
    eval("1", d)

    for k, v in renpy.minstore.__dict__.iteritems():
        if k not in d:
            d[k] = v

    # Create or reuse the corresponding module.
    if name in store_modules:
        sys.modules[name] = store_modules[name]
    else:
        store_modules[name] = sys.modules[name] = StoreModule(d)

    if parent:
        store_dicts[parent][var] = sys.modules[name]


class StoreBackup():
    """
    This creates a copy of the current store, as it was at the start of
the current statement.
    """

    def __init__(self):

        # The contents of the store for each store.
        self.store = { }

        # The contents of old for each store.
        self.old = { }

        # The contents of ever_been_changed for each store.
        self.ever_been_changed = { }

        for k in store_dicts:
            self.backup_one(k)

    def backup_one(self, name):

        d = store_dicts[name]

        self.store[name] = dict(d)
        self.old[name] = d.old.as_dict()
        self.ever_been_changed[name] = set(d.ever_been_changed)

    def restore_one(self, name):
        sd = store_dicts[name]

        sd.clear()
        sd.update(self.store[name])

        sd.old = DictItems(self.old[name])

        sd.ever_been_changed.clear()
        sd.ever_been_changed.update(self.ever_been_changed[name])

    def restore(self):

        for k in store_dicts:
            self.restore_one(k)


clean_store_backup = None


def make_clean_stores():
    """
    Copy the clean stores.
    """

    global clean_store_backup

    for _k, v in store_dicts.iteritems():

        v.ever_been_changed.clear()
        v.begin()

    clean_store_backup = StoreBackup()


def clean_stores():
    """
    Revert the store to the clean copy.
    """

    clean_store_backup.restore()


def clean_store(name):
    """
    Reverts the named store to its clean copy.
    """

    if not name.startswith("store."):
        name = "store." + name

    clean_store_backup.restore_one(name)


def reset_store_changes(name):

    if not name.startswith("store."):
        name = "store." + name

    sd = store_dicts[name]
    sd.begin()

# Code that computes reachable objects, which is used to filter
# the rollback list before rollback or serialization.


class NoRollback(object):
    """
    :doc: norollback class

Instances of classes inheriting from this class do not participate in
rollback. Objects reachable through an instance of a NoRollback class
only participate in rollback if they are reachable through other paths.
    """

    pass


# parents = [ ]

def reached(obj, reachable, wait):
    """
    [USER=305052]Param[/USER] obj: The object that was reached.
[USER=305052]Param[/USER] path: The path from the store via which it was reached.

`reachable`
A map from id(obj) to int. The int is 1 if the object was reached
normally, and 0 if it was reached, but inherits from NoRollback.

    """

    if wait:
        wait()

    idobj = id(obj)

    if idobj in reachable:
        return

    if isinstance(obj, (NoRollback, real_file)):  # @UndefinedVariable
        reachable[idobj] = 0
        return

    reachable[idobj] = 1

    # Since the store module is the roots, there's no need to
    # look into it.
    if isinstance(obj, StoreModule):
        return

    # parents.append(obj)

    try:
        # Treat as fields, indexed by strings.
        for v in vars(obj).itervalues():
            reached(v, reachable, wait)
    except:
        pass

    try:
        # Treat as iterable
        if not isinstance(obj, basestring):
            for v in obj.__iter__():
                reached(v, reachable, wait)
    except:
        pass

    try:
        # Treat as dict.
        for v in obj.itervalues():
            reached(v, reachable, wait)
    except:
        pass

    # parents.pop()


def reached_vars(store, reachable, wait):
    """
    Marks everything reachable from the variables in the store
or from the context info objects as reachable.

[USER=305052]Param[/USER] store: A map from variable name to variable value.
[USER=305052]Param[/USER] reachable: A dictionary mapping reached object ids to
the path by which the object was reached.
    """

    for v in store.itervalues():
        reached(v, reachable, wait)

    for c in renpy.game.contexts:
        reached(c.info, reachable, wait)
        reached(c.music, reachable, wait)
        for d in c.dynamic_stack:
            for v in d.itervalues():
                reached(v, reachable, wait)


# Code that replaces literals will calls to magic constructors.

class WrapNode(ast.NodeTransformer):

    def visit_ClassDef(self, n):
        n = self.generic_visit(n)

        if not n.bases:
            n.bases.append(ast.Name(id="object", ctx=ast.Load()))

        return n

    def visit_SetComp(self, n):
        return ast.Call(
            func=ast.Name(
                id="__renpy__set__",
                ctx=ast.Load()
                ),
            args=[ self.generic_visit(n) ],
            keywords=[ ],
            starargs=None,
            kwargs=None)

    def visit_Set(self, n):

        return ast.Call(
            func=ast.Name(
                id="__renpy__set__",
                ctx=ast.Load()
                ),
            args=[ self.generic_visit(n) ],
            keywords=[ ],
            starargs=None,
            kwargs=None)

    def visit_ListComp(self, n):
        return ast.Call(
            func=ast.Name(
                id="__renpy__list__",
                ctx=ast.Load()
                ),
            args=[ self.generic_visit(n) ],
            keywords=[ ],
            starargs=None,
            kwargs=None)

    def visit_List(self, n):
        if not isinstance(n.ctx, ast.Load):
            return self.generic_visit(n)

        return ast.Call(
            func=ast.Name(
                id="__renpy__list__",
                ctx=ast.Load()
                ),
            args=[ self.generic_visit(n) ],
            keywords=[ ],
            starargs=None,
            kwargs=None)

    def visit_DictComp(self, n):
        return ast.Call(
            func=ast.Name(
                id="__renpy__dict__",
                ctx=ast.Load()
                ),
            args=[ self.generic_visit(n) ],
            keywords=[ ],
            starargs=None,
            kwargs=None)

    def visit_Dict(self, n):

        return ast.Call(
            func=ast.Name(
                id="__renpy__dict__",
                ctx=ast.Load()
                ),
            args=[ self.generic_visit(n) ],
            keywords=[ ],
            starargs=None,
            kwargs=None)


wrap_node = WrapNode()


def wrap_hide(tree):
    """
    Wraps code inside a python hide or python early hide block inside a
function, so it gets its own scope that works the way Python expects
it to.
    """

    hide = ast.parse("""\
def _execute_python_hide(): pass;
_execute_python_hide()
""")

    for i in ast.walk(hide):
        ast.copy_location(i, hide.body[0])

    hide.body[0].body = tree.body
    tree.body = hide.body


unicode_re = re.compile(ur'[\u0080-\uffff]')


def unicode_sub(m):
    """
    If the string s contains a unicode character, make it into a
unicode string.
    """

    s = m.group(0)

    if not unicode_re.search(s):
        return s

    prefix = m.group(1)
    sep = m.group(2)
    body = m.group(3)

    if "u" not in prefix and "U" not in prefix:
        prefix = 'u' + prefix

    rv = prefix + sep + body + sep

    return rv


string_re = re.compile(r'([uU]?[rR]?)("""|"|\'\'\'|\')((\\.|.)*?)\2')


def escape_unicode(s):
    if unicode_re.search(s):
        s = string_re.sub(unicode_sub, s)

    return s


# Flags used by py_compile.
old_compile_flags = ( __future__.nested_scopes.compiler_flag
                      | __future__.with_statement.compiler_flag
                      )

new_compile_flags = (  old_compile_flags
                       | __future__.absolute_import.compiler_flag
                       | __future__.print_function.compiler_flag
                       | __future__.unicode_literals.compiler_flag
                       )


# A cache for the results of py_compile.
py_compile_cache = { }

# An old version of the same, that's preserved across reloads.
old_py_compile_cache = { }


# Duplicated from ast.py to prevent a gc cycle.
def fix_missing_locations(node, lineno, col_offset):
    if 'lineno' in node._attributes:
        if not hasattr(node, 'lineno'):
            node.lineno = lineno
        else:
            lineno = node.lineno
    if 'col_offset' in node._attributes:
        if not hasattr(node, 'col_offset'):
            node.col_offset = col_offset
        else:
            col_offset = node.col_offset
    for child in ast.iter_child_nodes(node):
        fix_missing_locations(child, lineno, col_offset)


def py_compile(source, mode, filename='<none>', lineno=1, ast_node=False, cache=True):
    """
    Compiles the given source code using the supplied codegenerator.
Lists, List Comprehensions, and Dictionaries are wrapped when
appropriate.

`source`
The source code, as a either a string, pyexpr, or ast module
node.

`mode`
One of "exec" or "eval".

`filename`
The filename the source comes from. If a pyexpr is given, the
filename embedded in the pyexpr is used.

`lineno`
The line number of the first line of source code. If a pyexpr is
given, the filename embedded in the pyexpr is used.

`ast_node`
Rather than returning compiled bytecode, returns the AST object
that would be used.
    """

    if ast_node:
        cache = False

    if isinstance(source, ast.Module):
        return compile(source, filename, mode)

    if isinstance(source, renpy.ast.PyExpr):
        filename = source.filename
        lineno = source.linenumber

    if cache:
        key = (lineno, filename, unicode(source), mode, renpy.script.MAGIC)

        rv = py_compile_cache.get(key, None)
        if rv is not None:
            return rv

        rv = old_py_compile_cache.get(key, None)
        if rv is not None:
            old_py_compile_cache[key] = rv
            return rv

        bytecode = renpy.game.script.bytecode_oldcache.get(key, None)
        if bytecode is not None:

            renpy.game.script.bytecode_newcache[key] = bytecode
            rv = marshal.loads(bytecode)
            py_compile_cache[key] = rv
            return rv

    source = unicode(source)
    source = source.replace("\r", "")
    source = escape_unicode(source)

    try:
        line_offset = lineno - 1

        if mode == "hide":
            py_mode = "exec"
        else:
            py_mode = mode

        try:
            flags = new_compile_flags
            tree = compile(source, filename, py_mode, ast.PyCF_ONLY_AST | flags, 1)
        except:
            flags = old_compile_flags
            tree = compile(source, filename, py_mode, ast.PyCF_ONLY_AST | flags, 1)

        tree = wrap_node.visit(tree)

        if mode == "hide":
            wrap_hide(tree)

        fix_missing_locations(tree, 1, 0)
        ast.increment_lineno(tree, lineno - 1)

        line_offset = 0

        if ast_node:
            return tree.body

        rv = compile(tree, filename, py_mode, flags, 1)

        if cache:
            py_compile_cache[key] = rv
            renpy.game.script.bytecode_newcache[key] = marshal.dumps(rv)
            renpy.game.script.bytecode_dirty = True

        return rv

    except SyntaxError as e:

        if e.lineno is not None:
            e.lineno += line_offset

        raise e


def py_compile_exec_bytecode(source, **kwargs):
    code = py_compile(source, 'exec', cache=False, **kwargs)
    return marshal.dumps(code)


def py_compile_hide_bytecode(source, **kwargs):
    code = py_compile(source, 'hide', cache=False, **kwargs)
    return marshal.dumps(code)


def py_compile_eval_bytecode(source, **kwargs):
    source = source.strip()
    code = py_compile(source, 'eval', cache=False, **kwargs)
    return marshal.dumps(code)


# Classes that are exported in place of the normal list, dict, and
# object.

# This is set to True whenever a mutation occurs. The save code uses
# this to check to see if a background-save is valid.
mutate_flag = True


def mutator(method):

    def do_mutation(self, *args, **kwargs):

        global mutate_flag

        mutated = renpy.game.log.mutated  # @UndefinedVariable

        if id(self) not in mutated:
            mutated[id(self)] = ( weakref.ref(self), self._clean())
            mutate_flag = True

        return method(self, *args, **kwargs)

    return do_mutation


class CompressedList(object):
    """
    Compresses the changes in a queue-like list. What this does is to try
to find a central sub-list for which has objects in both lists. It
stores the location of that in the new list, and then elements before
and after in the sub-list.

This only really works if the objects in the list are unique, but the
results are efficient even if this doesn't work.
    """

    def __init__(self, old, new):

        # Pick out a pivot element near the center of the list.
        new_center = (len(new) - 1) // 2
        new_pivot = new[new_center]

        # Find an element in the old list corresponding to the pivot.
        old_half = (len(old) - 1) // 2

        for i in range(0, old_half + 1):

            if old[old_half - i] is new_pivot:
                old_center = old_half - i
                break

            if old[old_half + i] is new_pivot:
                old_center = old_half + i
                break
        else:
            # If we couldn't, give up.
            self.pre = old
            self.start = 0
            self.end = 0
            self.post = [ ]

            return

        # Figure out the position of the overlap in the center of the two lists.
        new_start = new_center
        new_end = new_center + 1

        old_start = old_center
        old_end = old_center + 1

        len_new = len(new)
        len_old = len(old)

        while new_start and old_start and (new[new_start - 1] is old[old_start - 1]):
            new_start -= 1
            old_start -= 1

        while (new_end < len_new) and (old_end < len_old) and (new[new_end] is old[old_end]):
            new_end += 1
            old_end += 1

        # Now that we have this, we can put together the object.
        self.pre = list.__getslice__(old, 0, old_start)
        self.start = new_start
        self.end = new_end
        self.post = list.__getslice__(old, old_end, len_old)

    def decompress(self, new):
        return self.pre + new[self.start:self.end] + self.post

    def __repr__(self):
        return "<CompressedList {} [{}:{}] {}>".format(
            self.pre,
            self.start,
            self.end,
            self.post)


class RevertableList(list):

    def __init__(self, *args):
        log = renpy.game.log

        if log is not None:
            log.mutated[id(self)] = None

        list.__init__(self, *args)

    __delitem__ = mutator(list.__delitem__)
    __delslice__ = mutator(list.__delslice__)
    __setitem__ = mutator(list.__setitem__)
    __iadd__ = mutator(list.__iadd__)
    __imul__ = mutator(list.__imul__)
    append = mutator(list.append)
    extend = mutator(list.extend)
    insert = mutator(list.insert)
    pop = mutator(list.pop)
    remove = mutator(list.remove)
    reverse = mutator(list.reverse)
    sort = mutator(list.sort)

    def wrapper(method):  # E0213 [USER=3293592]NoSelf[/USER]
        def newmethod(*args, **kwargs):
            l = method(*args, **kwargs)
            return RevertableList(l)

        return newmethod

    __add__ = wrapper(list.__add__)
    __getslice__ = wrapper(list.__getslice__)

    def __mul__(self, other):
        if not isinstance(other, int):
            raise TypeError("can't multiply sequence by non-int of type '{}'.".format(type(other).__name__))

        return RevertableList(list.__mul__(self, other))

    __rmul__ = __mul__

    def _clean(self):
        """
        Gets a clean copy of this object before any mutation occurs.
        """

        return self[:]

    def _compress(self, clean):
        """
        Takes a clean copy of this object, compresses it, and returns compressed
information that can be passed to rollback.
        """

        if not self or not clean:
            return clean

        if renpy.config.list_compression_length is None:
            return clean

        if len(self) < renpy.config.list_compression_length or len(clean) < renpy.config.list_compression_length:
            return clean

        return CompressedList(clean, self)

    def _rollback(self, compressed):
        """
        Rolls this object back, using the information created by _compress.

Since compressed can come from a save file, this method also has to
recognize and deal with old data.
        """

        if isinstance(compressed, CompressedList):
            self[:] = compressed.decompress(self)
        else:
            self[:] = compressed


def revertable_range(*args):
    return RevertableList(range(*args))


def revertable_sorted(*args, **kwargs):
    return RevertableList(sorted(*args, **kwargs))


class RevertableDict(dict):

    def __init__(self, *args, **kwargs):
        log = renpy.game.log

        if log is not None:
            log.mutated[id(self)] = None

        dict.__init__(self, *args, **kwargs)

    __delitem__ = mutator(dict.__delitem__)
    __setitem__ = mutator(dict.__setitem__)
    clear = mutator(dict.clear)
    pop = mutator(dict.pop)
    popitem = mutator(dict.popitem)
    setdefault = mutator(dict.setdefault)
    update = mutator(dict.update)

    def list_wrapper(method):  # E0213 [USER=3293592]NoSelf[/USER]
        def newmethod(*args, **kwargs):
            return RevertableList(method(*args, **kwargs))  # E1102

        return newmethod

    keys = list_wrapper(dict.keys)
    values = list_wrapper(dict.values)
    items = list_wrapper(dict.items)

    del list_wrapper

    def copy(self):
        rv = RevertableDict()
        rv.update(self)
        return rv

    def _clean(self):
        return self.items()

    def _compress(self, clean):
        return clean

    def _rollback(self, compressed):
        self.clear()

        for k, v in compressed:
            self[k] = v


class RevertableSet(set):

    def __setstate__(self, state):
        if isinstance(state, tuple):
            self.update(state[0].keys())
        else:
            self.update(state)

    def __getstate__(self):
        rv = ({ i : True for i in self}, )
        return rv

    # Required to ensure that getstate and setstate are called.
    __reduce__ = object.__reduce__
    __reduce_ex__ = object.__reduce_ex__

    def __init__(self, *args):
        log = renpy.game.log

        if log is not None:
            log.mutated[id(self)] = None

        set.__init__(self, *args)

    __iand__ = mutator(set.__iand__)
    __ior__ = mutator(set.__ior__)
    __isub__ = mutator(set.__isub__)
    __ixor__ = mutator(set.__ixor__)
    add = mutator(set.add)
    clear = mutator(set.clear)
    difference_update = mutator(set.difference_update)
    discard = mutator(set.discard)
    intersection_update = mutator(set.intersection_update)
    pop = mutator(set.pop)
    remove = mutator(set.remove)
    symmetric_difference_update = mutator(set.symmetric_difference_update)
    union_update = mutator(set.update)
    update = mutator(set.update)

    def wrapper(method):  # [USER=3293592]NoSelf[/USER]
        def newmethod(*args, **kwargs):
            rv = method(*args, **kwargs)
            if isinstance(rv, (set, frozenset)):
                return RevertableSet(rv)
            else:
                return rv

        return newmethod

    __and__ = wrapper(set.__and__)
    __sub__ = wrapper(set.__sub__)
    __xor__ = wrapper(set.__xor__)
    __or__ = wrapper(set.__or__)
    copy = wrapper(set.copy)
    difference = wrapper(set.difference)
    intersection = wrapper(set.intersection)
    symmetric_difference = wrapper(set.symmetric_difference)
    union = wrapper(set.union)

    del wrapper

    def _clean(self):
        return list(self)

    def _compress(self, clean):
        return clean

    def _rollback(self, compressed):
        set.clear(self)
        set.update(self, compressed)


class RevertableObject(object):

    def __new__(cls, *args, **kwargs):
        self = super(RevertableObject, cls).__new__(cls)

        log = renpy.game.log
        if log is not None:
            log.mutated[id(self)] = None

        return self

    def __init__(self, *args, **kwargs):
        if (args or kwargs) and renpy.config.developer:
            raise TypeError("object() takes no parameters.")

    def __setattr__(self, attr, value):
        object.__setattr__(self, attr, value)

    def __delattr__(self, attr):
        object.__delattr__(self, attr)

    __setattr__ = mutator(__setattr__)
    __delattr__ = mutator(__delattr__)

    def _clean(self):
        return self.__dict__.copy()

    def _compress(self, clean):
        return clean

    def _rollback(self, compressed):
        self.__dict__.clear()
        self.__dict__.update(compressed)


class RollbackRandom(random.Random):
    """
    This is used for Random objects returned by renpy.random.Random.
    """

    def __init__(self):
        log = renpy.game.log

        if log is not None:
            log.mutated[id(self)] = None

        super(RollbackRandom, self).__init__()

    def _clean(self):
        return self.getstate()

    def _compress(self, clean):
        return clean

    def _rollback(self, compressed):
        super(RollbackRandom, self).setstate(compressed)

    setstate = mutator(random.Random.setstate)
    jumpahead = mutator(random.Random.jumpahead)
    getrandbits = mutator(random.Random.getrandbits)
    seed = mutator(random.Random.seed)
    random = mutator(random.Random.random)

    def Random(self, seed=None):
        """
        Returns a new RNG object separate from the main one.
        """

        if seed is None:
            seed = self.random()

        new = RollbackRandom()
        new.seed(seed)
        return new


class DetRandom(random.Random):
    """
    This is renpy.random.
    """

    def __init__(self):
        super(DetRandom, self).__init__()
        self.stack = [ ]

    def random(self):

        if self.stack:
            rv = self.stack.pop()
        else:
            rv = super(DetRandom, self).random()

        log = renpy.game.log

        if log.current is not None:
            log.current.random.append(rv)

        return rv

    def pushback(self, l):
        """
        Pushes the random numbers in l onto the stack so they will be generated
in the order given.
        """

        ll = l[:]
        ll.reverse()

        self.stack.extend(ll)

    def reset(self):
        """
        Resets the RNG, removing all of the pushbacked numbers.
        """

        del self.stack[:]

    def Random(self, seed=None):
        """
        Returns a new RNG object separate from the main one.
        """

        if seed is None:
            seed = self.random()

        new = RollbackRandom()
        new.seed(seed)
        return new


rng = DetRandom()

# This is the code that actually handles the logging and managing
# of the rollbacks.

generation = time.time()
serial = 0


class Rollback(renpy.object.Object):
    """
    Allows the state of the game to be rolled back to the point just
before a node began executing.

[USER=285527]ivar[/USER] context: A shallow copy of the context we were in before
we started executing the node. (Shallow copy also includes
a copy of the associated SceneList.)

[USER=285527]ivar[/USER] objects: A list of tuples, each containing an object and a
token of information that, when passed to the rollback method on
that object, causes that object to rollback.

[USER=285527]ivar[/USER] store: A list of updates to store that will cause the state
of the store to be rolled back to the start of node
execution. This is a list of tuples, either (key, value) tuples
representing a value that needs to be assigned to a key, or (key,)
tuples that mean the key should be deleted.

[USER=285527]ivar[/USER] checkpoint: True if this is a user-visible checkpoint,
false otherwise.

[USER=285527]ivar[/USER] purged: True if purge_unreachable has already been called on
this Rollback, False otherwise.

[USER=285527]ivar[/USER] random: A list of random numbers that were generated during the
execution of this element.
    """

    __version__ = 5

    identifier = None

    def __init__(self):

        super(Rollback, self).__init__()

        self.context = renpy.game.context().rollback_copy()

        self.objects = [ ]
        self.purged = False
        self.random = [ ]
        self.forward = None

        # A map of maps name -> (variable -> value)
        self.stores = { }

        # A map from store name to the changes to ever_been_changed that
        # need to be reverted.
        self.delta_ebc = { }

        # If true, we retain the data in this rollback when a load occurs.
        self.retain_after_load = False

        # True if this is a checkpoint we can roll back to.
        self.checkpoint = False

        # True if this is a hard checkpoint, where the rollback counter
        # decreases.
        self.hard_checkpoint = False

        # A unique identifier for this rollback object.

        global serial
        self.identifier = (generation, serial)
        serial += 1

    def after_upgrade(self, version):

        if version < 2:
            self.stores = { "store" : { } }

            for i in self.store:
                if len(i) == 2:
                    k, v = i
                    self.stores["store"][k] = v
                else:
                    k, = i
                    self.stores["store"][k] = deleted

        if version < 3:
            self.retain_after_load = False

        if version < 4:
            self.hard_checkpoint = self.checkpoint

        if version < 5:
            self.delta_ebc = { }

    def purge_unreachable(self, reachable, wait):
        """
        Adds objects that are reachable from the store of this
rollback to the set of reachable objects, and purges
information that is stored about totally unreachable objects.

Returns True if this is the first time this method has been
called, or False if it has already been called once before.
        """

        if self.purged:
            return False

        self.purged = True

        # Add objects reachable from the stores. (Objects that might be
        # unreachable at the moment.)
        for changes in self.stores.itervalues():
            for _k, v in changes.iteritems():
                if v is not deleted:
                    reached(v, reachable, wait)

        # Add in objects reachable through the context.
        reached(self.context.info, reachable, wait)
        for d in self.context.dynamic_stack:
            for v in d.itervalues():
                reached(v, reachable, wait)

        # Add in objects reachable through displayables.
        reached(self.context.scene_lists.get_all_displayables(), reachable, wait)

        # Purge object update information for unreachable objects.
        new_objects = [ ]

        for o, rb in self.objects:
            if reachable.get(id(o), 0):
                new_objects.append((o, rb))
                reached(rb, reachable, wait)
            else:
                if renpy.config.debug:
                    print("Removing unreachable:", o, file=renpy.log.real_stdout)
                    pass

        del self.objects[:]
        self.objects.extend(new_objects)

        return True

    def rollback(self):
        """
        Reverts the state of the game to what it was at the start of the
previous checkpoint.
        """

        for obj, roll in reversed(self.objects):
            if roll is not None:
                obj._rollback(roll)

        for name, changes in self.stores.iteritems():
            store = store_dicts.get(name, None)
            if store is None:
                continue

            for name, value in changes.iteritems():
                if value is deleted:
                    if name in store:
                        del store[name]
                else:
                    store[name] = value

        for name, changes in self.delta_ebc.iteritems():

            store = store_dicts.get(name, None)
            if store is None:
                continue

            store.ever_been_changed -= changes

        rng.pushback(self.random)

        renpy.game.contexts.pop()
        renpy.game.contexts.append(self.context)

    def rollback_control(self):
        """
        This rolls back only the control information, while leaving
the data information intact.
        """

        renpy.game.contexts.pop()
        renpy.game.contexts.append(self.context)


class RollbackLog(renpy.object.Object):
    """
    This class manages the list of Rollback objects.

[USER=285527]ivar[/USER] log: The log of rollback objects.

[USER=285527]ivar[/USER] current: The current rollback object. (Equivalent to
log[-1])

[USER=285527]ivar[/USER] rollback_limit: The number of steps left that we can
interactively rollback.

Not serialized:

[USER=285527]ivar[/USER] mutated: A dictionary that maps object ids to a tuple of
(weakref to object, information needed to rollback that object)
    """

    __version__ = 5

    nosave = [ 'old_store', 'mutated', 'identifier_cache' ]
    identifier_cache = None
    force_checkpoint = False

    def __init__(self):

        super(RollbackLog, self).__init__()

        self.log = [ ]
        self.current = None
        self.mutated = { }
        self.rollback_limit = 0
        self.rollback_is_fixed = False
        self.checkpointing_suspended = False
        self.fixed_rollback_boundary = None
        self.forward = [ ]
        self.old_store = { }

        # Did we just do a roll forward?
        self.rolled_forward = False

        # Reset the RNG on the creation of a new game.
        rng.reset()

        # True if we should retain data from here to the next checkpoint
        # on load.
        self.retain_after_load_flag = False

        # Has there been an interaction since the last time this log was
        # reset?
        self.did_interaction = True

        # Should we force a checkpoint before completing the current
        # statement.
        self.force_checkpoint = False

    def after_setstate(self):
        self.mutated = { }
        self.rolled_forward = False

    def after_upgrade(self, version):
        if version < 2:
            self.ever_been_changed = { "store" : set(self.ever_been_changed) }
        if version < 3:
            self.rollback_is_fixed = False
            self.fixed_rollback_boundary = None
        if version < 4:
            self.retain_after_load_flag = False

        if version < 5:

            # We changed what the rollback limit represents, so recompute it
            # here.
            if self.rollback_limit:
                nrbl = 0

                for rb in self.log[-self.rollback_limit:]:
                    if rb.hard_checkpoint:
                        nrbl += 1

                self.rollback_limit = nrbl

    def begin(self, force=False):
        """
        Called before a node begins executing, to indicate that the
state needs to be saved for rollbacking.
        """

        self.identifier_cache = None

        context = renpy.game.context()

        if not context.rollback:
            return

        # We only begin a checkpoint if the previous statement reached a checkpoint,
        # or an interaction took place. (Or we're forced.)
        ignore = True

        if force:
            ignore = False
        elif self.did_interaction:
            ignore = False
        elif self.current is not None:
            if self.current.checkpoint:
                ignore = False
            elif self.current.retain_after_load:
                ignore = False

        if ignore:
            return

        self.did_interaction = False

        if self.current is not None:
            self.complete(True)
        else:
            begin_stores()

        # If the log is too long, prune it.
        while len(self.log) > renpy.config.rollback_length:
            self.log.pop(0)

        # check for the end of fixed rollback
        if self.log and self.log[-1] == self.current:

            if self.current.context.current == self.fixed_rollback_boundary:
                self.rollback_is_fixed = False

            elif self.rollback_is_fixed and not self.forward:
                # A lack of rollback data in fixed rollback mode ends rollback.
                self.fixed_rollback_boundary = self.current.context.current
                self.rollback_is_fixed = False

        self.current = Rollback()
        self.current.retain_after_load = self.retain_after_load_flag

        self.log.append(self.current)

        self.mutated.clear()

        # Flag a mutation as having happened. This is used by the
        # save code.
        global mutate_flag
        mutate_flag = True

        self.rolled_forward = False

    def replace_node(self, old, new):
        """
        Replaces references to the `old` ast node with a reference to the
`new` ast node.
        """

        for i in self.log:
            i.context.replace_node(old, new)

    def complete(self, begin=False):
        """
        Called after a node is finished executing, before a save
begins, or right before a rollback is attempted. This may be
called more than once between calls to begin, and should always
be called after an update to the store but before a rollback
occurs.

`begin`
Should be true if called from begin().
        """

        if self.force_checkpoint:
            self.checkpoint(hard=False)
            self.force_checkpoint = False

        # Update self.current.stores with the changes from each store.
        # Also updates .ever_been_changed.
        for name, sd in store_dicts.iteritems():
            self.current.stores[name], self.current.delta_ebc[name] = sd.get_changes(begin)

        # Update the list of mutated objects and what we need to do to
        # restore them.

        for _i in xrange(4):

            del self.current.objects[:]

            try:
                for _k, v in self.mutated.iteritems():

                    if v is None:
                        continue

                    (ref, clean) = v

                    obj = ref()
                    if obj is None:
                        continue

                    compressed = obj._compress(clean)
                    self.current.objects.append((obj, compressed))

                break

            except RuntimeError:
                # This can occur when self.mutated is changed as we're
                # iterating over it.
                pass

    def get_roots(self):
        """
        Return a map giving the current roots of the store. This is a
map from a variable name in the store to the value of that
variable. A variable is only in this map if it has ever been
changed since the init phase finished.
        """

        rv = { }

        for store_name, sd in store_dicts.iteritems():
            for name in sd.ever_been_changed:
                if name in sd:
                    rv[store_name + "." + name] = sd[name]
                else:
                    rv[store_name + "." + name] = deleted

        for i in reversed(renpy.game.contexts[1:]):
            i.pop_dynamic_roots(rv)

        return rv

    def purge_unreachable(self, roots, wait=None):
        """
        This is called to purge objects that are unreachable from the
roots from the object rollback lists inside the Rollback entries.

This should be called immediately after complete(), so that there
are no changes queued up.
        """

        reachable = { }

        reached_vars(roots, reachable, wait)

        revlog = self.log[:]
        revlog.reverse()

        for i in revlog:
            if not i.purge_unreachable(reachable, wait):
                break

    def in_rollback(self):
        if self.forward:
            return True
        else:
            return False

    def in_fixed_rollback(self):
        return self.rollback_is_fixed

    def forward_info(self):
        """
        Returns the current forward info, if any.
        """

        if self.forward:

            name, data = self.forward[0]

            if self.current.context.current == name:
                return data

        return None

    def checkpoint(self, data=None, keep_rollback=False, hard=True):
        """
        Called to indicate that this is a checkpoint, which means
that the user may want to rollback to just before this
node.
        """

        if self.checkpointing_suspended:
            hard = False

        self.retain_after_load_flag = False

        if self.current.checkpoint:
            return

        if not renpy.game.context().rollback:
            return

        self.current.checkpoint = True

        if hard and (not self.current.hard_checkpoint):
            if self.rollback_limit < renpy.config.hard_rollback_limit:
                self.rollback_limit += 1
            self.current.hard_checkpoint = hard

        if self.in_fixed_rollback() and self.forward:
            # use data from the forward stack
            fwd_name, fwd_data = self.forward[0]
            if self.current.context.current == fwd_name:
                self.current.forward = fwd_data
                self.forward.pop(0)
            else:
                self.current.forward = data
                del self.forward[:]

        elif data is not None:
            if self.forward:
                # If the data is the same, pop it from the forward stack.
                # Otherwise, clear the forward stack.
                fwd_name, fwd_data = self.forward[0]

                if (self.current.context.current == fwd_name
                        and data == fwd_data
                        and (keep_rollback or self.rolled_forward)
                    ):
                    self.forward.pop(0)
                else:
                    del self.forward[:]

            # Log the data in case we roll back again.
            self.current.forward = data

    def suspend_checkpointing(self, flag):
        """
        Called to temporarily suspend checkpointing, so any rollback
will jump to prior to this statement
        """

        self.checkpointing_suspended = flag

    def block(self, purge=False):



        """
        Called to indicate that the user should not be able to rollback
through this checkpoint.
        """

        self.rollback_limit = 0
        renpy.game.context().force_checkpoint = True

        if purge:
            del self.log[:]

    def retain_after_load(self):
        """
        Called to return data from this statement until the next checkpoint
when the game is loaded.
        """

        if renpy.display.predict.predicting:
            return

        self.retain_after_load_flag = True
        self.current.retain_after_load = True
        renpy.game.context().force_checkpoint = True

    def fix_rollback(self):
        if not self.rollback_is_fixed and len(self.log) > 1:
            self.fixed_rollback_boundary = self.log[-2].context.current

    def can_rollback(self):
        """
        Returns True if we can rollback.
        """

        return self.rollback_limit > 0

    def load_failed(self):
        """
        This is called to try to recover when rollback fails.
        """

        if not renpy.config.load_failed_label:
            raise Exception("Couldn't find a place to stop rolling back. Perhaps the script changed in an incompatible way?")

        rb = self.log.pop()
        rb.rollback()

        while renpy.exports.call_stack_depth():
            renpy.exports.pop_call()

        renpy.game.contexts[0].force_checkpoint = True
        renpy.game.contexts[0].goto_label(renpy.config.load_failed_label)

        raise renpy.game.RestartTopContext()

    def rollback(self, checkpoints, force=False, label=None, greedy=True, on_load=False, abnormal=True, current_label=None):
        """
        This rolls the system back to the first valid rollback point
after having rolled back past the specified number of checkpoints.

If we're currently executing code, it's expected that complete()
will be called before a rollback is attempted.

force makes us throw an exception if we can't find a place to stop
rolling back, otherwise if we run out of log this call has no
effect.

`label`
A label that is called after rollback has finished, if the
label exists.

`greedy`
If true, rollback will keep going until just after the last
checkpoint. If False, it will stop immediately before the
current statement.

`on_load`
Should be true if this rollback is being called in response to a
load. Used to implement .retain_after_load()

`abnormal`
If true, treats this as an abnormal event, suppressing transitions
and so on.

`current_label`
A lable that is called when control returns to the current statement,
after rollback. (At most one of `current_label` and `label` can be
provided.)
        """

        # If we have exceeded the rollback limit, and don't have force,
        # give up.
        if checkpoints and (self.rollback_limit <= 0) and (not force):
            return

        self.suspend_checkpointing(False)
        # will always rollback to before suspension

        self.purge_unreachable(self.get_roots())

        revlog = [ ]

        # Find the place to roll back to.
        while self.log:
            rb = self.log.pop()
            revlog.append(rb)

            if rb.hard_checkpoint:
                self.rollback_limit -= 1

            if rb.hard_checkpoint or (on_load and rb.checkpoint):
                checkpoints -= 1

            if checkpoints <= 0:
                if renpy.game.script.has_label(rb.context.current):
                    break

        else:
            # Otherwise, just give up.

            revlog.reverse()
            self.log.extend(revlog)

            if force:
                self.load_failed()
            else:
                print("Can't find a place to rollback to. Not rolling back.")

            return

        force_checkpoint = False

        # Try to rollback to just after the previous checkpoint.
        while greedy and self.log and (self.rollback_limit > 0):

            rb = self.log[-1]

            if not renpy.game.script.has_label(rb.context.current):
                break

            if rb.hard_checkpoint:
                break

            revlog.append(self.log.pop())

        # Decide if we're replacing the current context (rollback command),
        # or creating a new set of contexts (loading).
        if renpy.game.context().rollback:
            replace_context = False
            other_contexts = [ ]

        else:
            replace_context = True
            other_contexts = renpy.game.contexts[1:]
            renpy.game.contexts = renpy.game.contexts[0:1]

        if on_load and revlog[-1].retain_after_load:
            retained = revlog.pop()
            self.retain_after_load_flag = True
        else:
            retained = None

        come_from = None

        if current_label is not None:
            come_from = renpy.game.context().current
            label = current_label

        # Actually roll things back.
        for rb in revlog:
            rb.rollback()

            if rb.context.current == self.fixed_rollback_boundary:
                self.rollback_is_fixed = True

            if rb.forward is not None:
                self.forward.insert(0, (rb.context.current, rb.forward))

        if retained is not None:
            retained.rollback_control()
            self.log.append(retained)

        if (label is not None) and (come_from is None):
            come_from = renpy.game.context().current

        if come_from is not None:
            renpy.game.context().come_from(come_from, label)

        # Disable the next transition, as it's pointless. (Only when not used with a label.)
        renpy.game.interface.suppress_transition = abnormal

        # If necessary, reset the RNG.
        if force:
            rng.reset()
            del self.forward[:]

        # Flag that we're in the transition immediately after a rollback.
        renpy.game.after_rollback = abnormal

        # Stop the sounds.
        renpy.audio.audio.rollback()

        # Stop any hiding in progress.
        for i in renpy.game.contexts:
            i.scene_lists.remove_all_hidden()

        renpy.game.contexts.extend(other_contexts)

        begin_stores()

        # Restart the context or the top context.
        if replace_context:

            if force_checkpoint:
                renpy.game.contexts[0].force_checkpoint = True

            raise renpy.game.RestartTopContext()

        else:

            if force_checkpoint:
                renpy.game.context().force_checkpoint = True

            raise renpy.game.RestartContext()

    def freeze(self, wait=None):
        """
        This is called to freeze the store and the log, in preparation
for serialization. The next call on log should either be
unfreeze (called after a serialization reload) or discard_freeze()
(called after the save is complete).
        """

        # Purge unreachable objects, so we don't save them.
        self.complete(False)
        roots = self.get_roots()
        self.purge_unreachable(roots, wait=wait)

        # The current is not purged.
        self.current.purged = False

        return roots

    def discard_freeze(self):
        """
        Called to indicate that we will not be restoring from the
frozen state.
        """

    def unfreeze(self, roots, label=None):
        """
        Used to unfreeze the game state after a load of this log
object. This call will always throw an exception. If we're
lucky, it's the one that indicates load was successful.

[USER=305052]Param[/USER] roots: The roots returned from freeze.

[USER=305052]Param[/USER] label: The label that is jumped to in the game script
after rollback has finished, if it exists.
        """

        # Fix up old screens.
        renpy.display.screen.before_restart()  # @UndefinedVariable

        # Set us up as the game log.
        renpy.game.log = self

        clean_stores()
        renpy.translation.init_translation()

        for name, value in roots.iteritems():

            if "." in name:
                store_name, name = name.rsplit(".", 1)
            else:
                store_name = "store"

            if store_name not in store_dicts:
                continue

            store = store_dicts[store_name]
            store.ever_been_changed.add(name)

            if value is deleted:
                if name in store:
                    del store[name]
            else:
                store[name] = value

        # Now, rollback to an acceptable point.

        greedy = renpy.session.pop("_greedy_rollback", False)
        self.rollback(0, force=True, label=label, greedy=greedy, on_load=True)

        # Because of the rollback, we never make it this far.

    def build_identifier_cache(self):

        if self.identifier_cache is not None:
            return

        rollback_limit = self.rollback_limit
        checkpoints = 1

        self.identifier_cache = { }

        for i in reversed(self.log):

            if i.identifier is not None:
                if renpy.game.script.has_label(i.context.current):
                    self.identifier_cache[i.identifier] = checkpoints

            if i.hard_checkpoint:
                checkpoints += 1

            if i.checkpoint:
                rollback_limit -= 1

            if not rollback_limit:
                break

    def get_identifier_checkpoints(self, identifier):
        self.build_identifier_cache()
        return self.identifier_cache.get(identifier, None)


def py_exec_bytecode(bytecode, hide=False, globals=None, locals=None, store="store"):  # @ReservedAssignment

    if hide:
        locals = { }  # @ReservedAssignment

    if globals is None:
        globals = store_dicts[store]  # @ReservedAssignment

    if locals is None:
        locals = globals  # @ReservedAssignment

    exec bytecode in globals, locals


def py_exec(source, hide=False, store=None):

    if store is None:
        store = store_dicts["store"]

    if hide:
        locals = { }  # @ReservedAssignment
    else:
        locals = store  # @ReservedAssignment

    exec py_compile(source, 'exec') in store, locals


def py_eval_bytecode(bytecode, globals=None, locals=None):  # @ReservedAssignment

    if globals is None:
        globals = store_dicts["store"]  # @ReservedAssignment

    if locals is None:
        locals = globals  # @ReservedAssignment

    return eval(bytecode, globals, locals)


def py_eval(code, globals=None, locals=None):  # @ReservedAssignment
    if isinstance(code, basestring):
        code = py_compile(code, 'eval')

    return py_eval_bytecode(code, globals, locals)


def store_eval(code, globals=None, locals=None):

    if globals is None:
        globals = sys._getframe(1).f_globals

    return py_eval(code, globals, locals)


def raise_at_location(e, loc):
    """
    Raises `e` (which must be an Exception object) at location `loc`.

`loc`
A location, which should be a (filename, line_number) tuple.
    """

    filename, line = loc

    node = ast.parse("raise e", filename)
    ast.increment_lineno(node, line - 1)
    code = compile(node, filename, 'exec')

    # PY3 - need to change to exec().
    exec code in { "e" : e }


# This was used to proxy accesses to the store. Now it's kept around to deal
# with cases where it might have leaked into a pickle.
class StoreProxy(object):

    def __getattr__(self, k):
        return getattr(renpy.store, k)  # @UndefinedVariable

    def __setattr__(self, k, v):
        setattr(renpy.store, k, v)  # @UndefinedVariable

    def __delattr__(self, k):
        delattr(renpy.store, k)  # @UndefinedVariable


# Code for pickling bound methods.
def method_pickle(method):
    name = method.im_func.__name__

    obj = method.im_self

    if obj is None:
        obj = method.im_class

    return method_unpickle, (obj, name)


def method_unpickle(obj, name):
    return getattr(obj, name)

# Code for pickling modules.


def module_pickle(module):
    if renpy.config.developer:
        raise Exception("Could not pickle {!r}.".format(module))

    return module_unpickle, (module.__name__,)


def module_unpickle(name):
    return __import__(name)


import copy_reg
import types

copy_reg.pickle(types.MethodType, method_pickle)
copy_reg.pickle(types.ModuleType, module_pickle)


.......
.....
thats the long version the short version.
Code:
I'm sorry, but an uncaught exception occurred.

While running game code:
  File "game/script.rpy", line 2, in script
    if steamConfig:
  File "game/script.rpy", line 2, in <module>
    if steamConfig:
NameError: name 'steamConfig' is not defined

-- Full Traceback ------------------------------------------------------------

Full traceback:
  File "game/script.rpy", line 2, in script
    if steamConfig:
  File "C:\Program Files (x86)\fuck you bitch\steamapps\common\Being a DIK\renpy\ast.py", line 1830, in execute
    if renpy.python.py_eval(condition):
  File "C:\Program Files (x86)\fuck you bitch\steamapps\common\Being a DIK\renpy\python.py", line 2035, in py_eval
    return py_eval_bytecode(code, globals, locals)
  File "C:\Program Files (x86)\fuck you bitch\steamapps\common\Being a DIK\renpy\python.py", line 2028, in py_eval_bytecode
    return eval(bytecode, globals, locals)
  File "game/script.rpy", line 2, in <module>
    if steamConfig:
NameError: name 'steamConfig' is not defined

Windows-8-6.2.9200
Ren'Py 7.3.2.320
 
Sun Jan 24 23:21:12 2021
 

Sngo

Active Member
May 9, 2020
540
3,542
I know that hardly a dev/modder takes some requests into consideration, but while I was replaying the Episode 4, something bugged me, and it's the obvious Maya+Josi path vs the Jade Path. Considering that in the Episode 2 and in the Episode 5 there's a mod that allows multiple paths to be executed at once, is it possible to make an addition to the mod to support it? Yeah, I know that it's old stuff, and I also know that's possible to define the variable on the cheat menu, but it would mean a lot for me to allow both paths in normal conditions.

Even if it's not possible due to some required coding, or even if it's pointless since it's old stuff and already possible on the cheat menu, I would like to be able to see both of scenes.
That would be dope if possible to include in next update.
 

CitDCypher

Newbie
Jul 26, 2017
97
890
Hi and thanks for your hard work. I just have a question. Is it possible to only install the cheat part of this mod? If so, which files do I need to move over or not move over? I know I can use console command for cheating purposes but i'd like to have a more convenient method.
 

mancible

New Member
Jul 6, 2017
3
0
So the grey screen only seems to open when I push the cheats button, but it also isn't showing the outcomes of choices like it used to.

Tried deleting game folder and adding from the download and got the same error as others. Then tried to install the one you uploaded 1 page back and got the same error as the person posted in response.
1612498490043.png

Scrappy you've spoiled me, It's so much more fun to at least have the option to see what the outcome of your choice will be, it's hard to play with out that. I hope you have time to update good sir! You're mod is the best!
 
Last edited:

Hotkillerz

Member
May 1, 2017
379
212
im guessing the mod fix that Scrappy posted isnt working as im seeing everyone is having the same issue that i am. u put the fix in the folder replace the files and the error shows up when u open the game.
 

Sculp

Newbie
Sep 3, 2018
33
6
im guessing the mod fix that Scrappy posted isnt working as im seeing everyone is having the same issue that i am. u put the fix in the folder replace the files and the error shows up when u open the game.
I guess it is to big as a game to make a mod for it. There are just too many choices and it has a big impcat in the mod as far as I know
 

Hotkillerz

Member
May 1, 2017
379
212
I guess it is to big as a game to make a mod for it. There are just too many choices and it has a big impcat in the mod as far as I know
funny thing is is its only doing it for the steam version do it for any other version it works fine.
 
Jul 8, 2020
40
5
Does the full unlocked scenes in this cheatmod the entire scenes, or are they still limited to our chick-dik scores. Like if we are full diks, do scenes only available for chicks unlocked as well?
 

chimidot

Member
Oct 21, 2017
225
138
hi, i get this error when i talk to Cathrin on Swiper in episode 6 in the library.. when i select ' ok, but i don't see the point of doing that' . what can i do? can someone please help me?

Code:
I'm sorry, but an uncaught exception occurred.

While running game code:
  File "game/season2/scripts/freeroam/episode6/ep6_freeroam_library.rpy", line 98, in script
    $ result = ui.interact()
  File "game/season2/scripts/freeroam/episode6/ep6_freeroam_library.rpy", line 98, in <module>
    $ result = ui.interact()
  File "game/season2/scripts/phone/swyper/chats/swyper_chat_catrin_s2.rpy", line 1, in execute
  File "game/season2/scripts/phone/swyper/chats/swyper_chat_catrin_s2.rpy", line 1, in execute
  File "game/season2/scripts/phone/swyper/chats/swyper_chat_catrin_s2.rpy", line 32, in execute
  File "game/season2/scripts/phone/swyper/chats/swyper_chat_catrin_s2.rpy", line 50, in execute
  File "game/season2/scripts/phone/swyper/chats/swyper_chat_catrin_s2.rpy", line 55, in execute
  File "game/season2/scripts/phone/swyper/chats/swyper_chat_catrin_s2.rpy", line 56, in execute
IndexError: list index out of range

-- Full Traceback ------------------------------------------------------------

Full traceback:
  File "game/season2/scripts/freeroam/episode6/ep6_freeroam_library.rpy", line 98, in script
    $ result = ui.interact()
  File "G:\Digital Desire\JOCURI\BeingADIK-0.6.0-pc-lin\renpy\ast.py", line 912, in execute
    renpy.python.py_exec_bytecode(self.code.bytecode, self.hide, store=self.store)
  File "G:\Digital Desire\JOCURI\BeingADIK-0.6.0-pc-lin\renpy\python.py", line 2004, in py_exec_bytecode
    exec bytecode in globals, locals
  File "game/season2/scripts/freeroam/episode6/ep6_freeroam_library.rpy", line 98, in <module>
    $ result = ui.interact()
  File "G:\Digital Desire\JOCURI\BeingADIK-0.6.0-pc-lin\renpy\ui.py", line 295, in interact
    rv = renpy.game.interface.interact(roll_forward=roll_forward, **kwargs)
  File "G:\Digital Desire\JOCURI\BeingADIK-0.6.0-pc-lin\renpy\display\core.py", line 2699, in interact
    repeat, rv = self.interact_core(preloads=preloads, trans_pause=trans_pause, **kwargs)
  File "G:\Digital Desire\JOCURI\BeingADIK-0.6.0-pc-lin\renpy\display\core.py", line 3091, in interact_core
    root_widget.visit_all(lambda i : i.per_interact())
  File "G:\Digital Desire\JOCURI\BeingADIK-0.6.0-pc-lin\renpy\display\core.py", line 541, in visit_all
    d.visit_all(callback, seen)
  File "G:\Digital Desire\JOCURI\BeingADIK-0.6.0-pc-lin\renpy\display\core.py", line 541, in visit_all
    d.visit_all(callback, seen)
  File "G:\Digital Desire\JOCURI\BeingADIK-0.6.0-pc-lin\renpy\display\core.py", line 541, in visit_all
    d.visit_all(callback, seen)
  File "G:\Digital Desire\JOCURI\BeingADIK-0.6.0-pc-lin\renpy\display\screen.py", line 430, in visit_all
    callback(self)
  File "G:\Digital Desire\JOCURI\BeingADIK-0.6.0-pc-lin\renpy\display\core.py", line 3091, in <lambda>
    root_widget.visit_all(lambda i : i.per_interact())
  File "G:\Digital Desire\JOCURI\BeingADIK-0.6.0-pc-lin\renpy\display\screen.py", line 440, in per_interact
    self.update()
  File "G:\Digital Desire\JOCURI\BeingADIK-0.6.0-pc-lin\renpy\display\screen.py", line 625, in update
    self.screen.function(**self.scope)
  File "game/season2/scripts/phone/swyper/chats/swyper_chat_catrin_s2.rpy", line 1, in execute
  File "game/season2/scripts/phone/swyper/chats/swyper_chat_catrin_s2.rpy", line 1, in execute
  File "game/season2/scripts/phone/swyper/chats/swyper_chat_catrin_s2.rpy", line 32, in execute
  File "game/season2/scripts/phone/swyper/chats/swyper_chat_catrin_s2.rpy", line 50, in execute
  File "game/season2/scripts/phone/swyper/chats/swyper_chat_catrin_s2.rpy", line 55, in execute
  File "game/season2/scripts/phone/swyper/chats/swyper_chat_catrin_s2.rpy", line 56, in execute
  File "<screen language>", line 56, in <module>
IndexError: list index out of range

Windows-8-6.2.9200
Ren'Py 7.3.2.320
Being a DIK 0.6.0
Fri Mar 05 03:28:14 2021
 
  • Like
Reactions: mikecd199817

Deleted member 3313072

Engaged Member
Jan 26, 2021
2,526
3,052
Hey scrappy, loved the mod, but it screwed up one thing for me in my Pure Jill run.

The phone said I never punched Tybalt. And I also know I never punched him.

But the rain date, Jill said I did.

I don't know how that's going to play out in the future, but letting you know it's there.
 
  • Like
Reactions: mikecd199817

animeboi314

Newbie
Feb 18, 2020
18
14
Does anyone know when this is getting fixed? I mean it says it's for version 6.1 but I still get the error and I would really like to have the mod since I always use it to change my affinity for all the choices and mess around with the variables.
 
  • Like
Reactions: mikecd199817
4.70 star(s) 31 Votes