958 lines
26 KiB
Text
958 lines
26 KiB
Text
# 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.
|
|
|
|
init -1500 python:
|
|
##########################################################################
|
|
# File contstants.
|
|
|
|
_weekday_name_long = [
|
|
_("{#weekday}Monday"),
|
|
_("{#weekday}Tuesday"),
|
|
_("{#weekday}Wednesday"),
|
|
_("{#weekday}Thursday"),
|
|
_("{#weekday}Friday"),
|
|
_("{#weekday}Saturday"),
|
|
_("{#weekday}Sunday"),
|
|
]
|
|
|
|
|
|
_weekday_name_short = [
|
|
_("{#weekday_short}Mon"),
|
|
_("{#weekday_short}Tue"),
|
|
_("{#weekday_short}Wed"),
|
|
_("{#weekday_short}Thu"),
|
|
_("{#weekday_short}Fri"),
|
|
_("{#weekday_short}Sat"),
|
|
_("{#weekday_short}Sun"),
|
|
]
|
|
|
|
_month_name_long = [
|
|
_("{#month}January"),
|
|
_("{#month}February"),
|
|
_("{#month}March"),
|
|
_("{#month}April"),
|
|
_("{#month}May"),
|
|
_("{#month}June"),
|
|
_("{#month}July"),
|
|
_("{#month}August"),
|
|
_("{#month}September"),
|
|
_("{#month}October"),
|
|
_("{#month}November"),
|
|
_("{#month}December"),
|
|
]
|
|
|
|
|
|
_month_name_short = [
|
|
_("{#month_short}Jan"),
|
|
_("{#month_short}Feb"),
|
|
_("{#month_short}Mar"),
|
|
_("{#month_short}Apr"),
|
|
_("{#month_short}May"),
|
|
_("{#month_short}Jun"),
|
|
_("{#month_short}Jul"),
|
|
_("{#month_short}Aug"),
|
|
_("{#month_short}Sep"),
|
|
_("{#month_short}Oct"),
|
|
_("{#month_short}Nov"),
|
|
_("{#month_short}Dec"),
|
|
]
|
|
|
|
def _strftime(format, t):
|
|
"""
|
|
A version of strftime that's meant to work with Ren'Py's translation
|
|
system.
|
|
"""
|
|
rv = format
|
|
|
|
month = t[1] - 1
|
|
wday = t[6]
|
|
|
|
rv = rv.replace("%a", __(_weekday_name_short[wday]))
|
|
rv = rv.replace("%A", __(_weekday_name_long[wday]))
|
|
rv = rv.replace("%b", __(_month_name_short[month]))
|
|
rv = rv.replace("%B", __(_month_name_long[month]))
|
|
|
|
if "%" in rv:
|
|
import time
|
|
rv = time.strftime(rv.encode("utf-8"), t).decode("utf-8")
|
|
|
|
return rv
|
|
|
|
|
|
##########################################################################
|
|
# File functions
|
|
|
|
config.linear_saves_page_size = None
|
|
config.quicksave_slots = 10
|
|
|
|
# The number of file pages per folder.
|
|
config.file_pages_per_folder = 100
|
|
|
|
if persistent._file_page is None:
|
|
persistent._file_page = "1"
|
|
|
|
if persistent._file_folder is None:
|
|
persistent._file_folder = 0
|
|
|
|
if persistent._file_page_name is None:
|
|
persistent._file_page_name = { }
|
|
|
|
config.file_page_names = [ ]
|
|
|
|
config.predict_file_pages = True
|
|
|
|
def __slotname(name, page=None, slot=False):
|
|
|
|
if slot:
|
|
return name
|
|
|
|
if page is None:
|
|
page = persistent._file_page
|
|
|
|
try:
|
|
page = int(page)
|
|
page = page + persistent._file_folder * config.file_pages_per_folder
|
|
except ValueError:
|
|
pass
|
|
|
|
if config.linear_saves_page_size is not None:
|
|
try:
|
|
page = int(page)
|
|
name = int(name)
|
|
return str((page - 1) * config.linear_saves_page_size + name)
|
|
except ValueError:
|
|
pass
|
|
|
|
return str(page) + "-" + str(name)
|
|
|
|
def __newest_slot():
|
|
"""
|
|
Returns the name of the newest slot.
|
|
"""
|
|
|
|
return renpy.newest_slot(r'\d+')
|
|
|
|
def __unused_slot_name(page):
|
|
"""
|
|
Returns an unused name of a slot on the current page. (This will
|
|
likely be a very big number, as it's based on the current unix time.)
|
|
"""
|
|
|
|
import time
|
|
|
|
rv = int(time.time())
|
|
|
|
while True:
|
|
if not renpy.can_load(__slotname(str(rv), page)):
|
|
return str(rv)
|
|
|
|
rv += 1
|
|
|
|
def FileCurrentPage():
|
|
"""
|
|
:doc: file_action_function
|
|
|
|
Returns the current file page as a string.
|
|
"""
|
|
|
|
return str(persistent._file_page)
|
|
|
|
def FileUsedSlots(page=None, highest_first=True):
|
|
"""
|
|
:doc: file_action_function
|
|
|
|
Returns a list of used numeric file slots on the page.
|
|
|
|
`page`
|
|
The name of the page that will be scanned. If None, the current page
|
|
is used.
|
|
|
|
`highest_first`
|
|
If true, the highest-numbered file slot is listed first.
|
|
Otherwise, the lowest-numbered slot is listed first.
|
|
"""
|
|
|
|
regexp = __slotname(r'\d+', page)
|
|
|
|
rv = [ ]
|
|
|
|
for fn in renpy.list_slots(regexp=regexp):
|
|
_page, _, slot = fn.partition('-')
|
|
|
|
rv.append(int(slot))
|
|
|
|
rv.sort()
|
|
if highest_first:
|
|
rv.reverse()
|
|
|
|
return rv
|
|
|
|
def FileLoadable(name, page=None, slot=False):
|
|
"""
|
|
:doc: file_action_function
|
|
|
|
This is a function that returns true
|
|
if the file is loadable, and false otherwise.
|
|
"""
|
|
|
|
return renpy.can_load(__slotname(name, page, slot))
|
|
|
|
def FileScreenshot(name, empty=None, page=None, slot=False):
|
|
"""
|
|
:doc: file_action_function
|
|
|
|
Returns the screenshot associated with the given file. If the
|
|
file is not loadable, then `empty` is returned, unless it's None,
|
|
in which case, a Null displayable is created.
|
|
|
|
The return value is a displayable.
|
|
"""
|
|
|
|
screenshot = renpy.slot_screenshot(__slotname(name, page, slot=slot))
|
|
|
|
if screenshot is not None:
|
|
return screenshot
|
|
|
|
if empty is not None:
|
|
return empty
|
|
else:
|
|
return Null(config.thumbnail_width, config.thumbnail_height)
|
|
|
|
|
|
def FileTime(name, format=_("%b %d, %H:%M"), empty="", page=None, slot=False):
|
|
"""
|
|
:doc: file_action_function
|
|
|
|
Returns the time the file was saved, formatted according
|
|
to the supplied `format`. If the file is not found, `empty` is
|
|
returned.
|
|
|
|
The return value is a string.
|
|
"""
|
|
|
|
mtime = renpy.slot_mtime(__slotname(name, page, slot))
|
|
|
|
if mtime is None:
|
|
return empty
|
|
|
|
import time
|
|
|
|
format = renpy.translation.translate_string(format)
|
|
return _strftime(format, time.localtime(mtime))
|
|
|
|
def FileJson(name, key=None, empty=None, missing=None, page=None, slot=False):
|
|
"""
|
|
:doc: file_action_function
|
|
|
|
Accesses the Json information associated with `name`.
|
|
|
|
If `key` is None, returns the entire Json other object, or `empty` if the slot
|
|
is empty.
|
|
|
|
Otherwise, this returns json[key] if `key` is defined on the json object of the save,
|
|
`missing` if there is a save with the given name, but it does not contain `key`, or
|
|
`empty` if the save slot is empty.
|
|
|
|
Json is added to a save slot by callbacks registered using :var:`config.save_json_callbacks`.
|
|
"""
|
|
|
|
json = renpy.slot_json(__slotname(name, page, slot))
|
|
|
|
if json is None:
|
|
return empty
|
|
|
|
if key is None:
|
|
return json
|
|
|
|
return json.get(key, missing)
|
|
|
|
|
|
def FileSaveName(name, empty="", page=None, slot=False):
|
|
"""
|
|
:doc: file_action_function
|
|
|
|
Return the save_name that was in effect when the file was saved,
|
|
or `empty` if the file does not exist.
|
|
"""
|
|
|
|
return FileJson(name, "_save_name", empty=empty, missing=empty, page=page, slot=slot)
|
|
|
|
def FileNewest(name, page=None, slot=False):
|
|
"""
|
|
:doc: file_action_function
|
|
|
|
Returns True if this is the newest file slot, or False otherwise.
|
|
"""
|
|
|
|
return __newest_slot() == __slotname(name, page, slot)
|
|
|
|
class FileSave(Action, DictEquality):
|
|
"""
|
|
:doc: file_action
|
|
|
|
Saves the file.
|
|
|
|
The button with this slot is selected if it's marked as the
|
|
newest save file.
|
|
|
|
`name`
|
|
The name of the slot to save to. If None, an unused slot
|
|
(a large number based on the current time) will be used.
|
|
|
|
`confirm`
|
|
If true, then we will prompt before overwriting a file.
|
|
|
|
`newest`
|
|
Ignored.
|
|
|
|
`page`
|
|
The name of the page that the slot is on. If None, the current
|
|
page is used.
|
|
|
|
`cycle`
|
|
If true, then saves on the supplied page will be cycled before
|
|
being shown to the user. :var:`config.quicksave_slots` slots are
|
|
used in the cycle.
|
|
|
|
`slot`
|
|
If True, `name` is taken to be a slot name, and `page` is ignored.
|
|
"""
|
|
|
|
alt = "Save slot [text]"
|
|
slot = None
|
|
|
|
def __init__(self, name, confirm=True, newest=True, page=None, cycle=False, slot=False):
|
|
if name is None:
|
|
name = __unused_slot_name(page)
|
|
|
|
self.name = name
|
|
self.confirm = confirm
|
|
self.page = page
|
|
self.cycle = cycle
|
|
self.slot = slot
|
|
|
|
try:
|
|
self.alt = __("Save slot %s: [text]") % (name,)
|
|
except:
|
|
self.alt = "Save slot %s: [text]" % (name,)
|
|
|
|
def __call__(self):
|
|
|
|
if not self.get_sensitive():
|
|
return
|
|
|
|
fn = __slotname(self.name, self.page, self.slot)
|
|
|
|
if renpy.scan_saved_game(fn):
|
|
if self.confirm:
|
|
layout.yesno_screen(layout.OVERWRITE_SAVE, FileSave(self.name, False, False, self.page, cycle=self.cycle, slot=self.slot))
|
|
return
|
|
|
|
if self.cycle:
|
|
renpy.renpy.loadsave.cycle_saves(self.page + "-", config.quicksave_slots)
|
|
|
|
renpy.save(fn, extra_info=save_name)
|
|
|
|
renpy.restart_interaction()
|
|
|
|
def get_sensitive(self):
|
|
if _in_replay:
|
|
return False
|
|
elif main_menu:
|
|
return False
|
|
elif (self.page or persistent._file_page) == "auto":
|
|
return False
|
|
else:
|
|
return True
|
|
|
|
def get_selected(self):
|
|
if not self.confirm:
|
|
return False
|
|
|
|
return __newest_slot() == __slotname(self.name, self.page, self.slot)
|
|
|
|
class FileLoad(Action, DictEquality):
|
|
"""
|
|
:doc: file_action
|
|
|
|
Loads the file.
|
|
|
|
`name`
|
|
The name of the slot to load from. If None, an unused slot will be
|
|
used, and hence the file will not be loadable.
|
|
|
|
`confirm`
|
|
If true and not at the main menu, prompt for confirmation before loading the file.
|
|
|
|
`page`
|
|
The page that the file will be loaded from. If None, the
|
|
current page is used.
|
|
|
|
`newest`
|
|
If true, the button is selected if this is the newest file.
|
|
|
|
`cycle`
|
|
Ignored.
|
|
|
|
`slot`
|
|
If True, `name` is taken to be a slot name, and `page` is ignored.
|
|
"""
|
|
|
|
alt = "Load slot [text]"
|
|
slot = None
|
|
|
|
def __init__(self, name, confirm=True, page=None, newest=True, cycle=False, slot=False):
|
|
|
|
if name is None:
|
|
name = __unused_slot_name(page)
|
|
|
|
self.name = name
|
|
self.confirm = confirm
|
|
self.page = page
|
|
self.newest = newest
|
|
self.slot = slot
|
|
|
|
try:
|
|
self.alt = __("Load slot %s: [text]") % (name,)
|
|
except:
|
|
self.alt = "Load slot %s: [text]" % (name,)
|
|
|
|
def __call__(self):
|
|
|
|
if not self.get_sensitive():
|
|
return
|
|
|
|
fn = __slotname(self.name, self.page, self.slot)
|
|
|
|
if not main_menu:
|
|
if self.confirm:
|
|
if config.autosave_on_quit and not fn.startswith("auto-"):
|
|
renpy.loadsave.force_autosave()
|
|
layout.yesno_screen(layout.LOADING, FileLoad(self.name, False, self.page, slot=self.slot))
|
|
return
|
|
|
|
renpy.load(fn)
|
|
|
|
def get_sensitive(self):
|
|
if _in_replay:
|
|
return False
|
|
|
|
return renpy.can_load(__slotname(self.name, self.page, self.slot))
|
|
|
|
def get_selected(self):
|
|
if not self.confirm or not self.newest:
|
|
return False
|
|
|
|
return __newest_slot() == __slotname(self.name, self.page, self.slot)
|
|
|
|
@renpy.pure
|
|
class FileDelete(Action, DictEquality):
|
|
"""
|
|
:doc: file_action
|
|
|
|
Deletes the file.
|
|
|
|
`name`
|
|
The name of the slot to delete.
|
|
|
|
`confirm`
|
|
If true and not at the main menu, prompt for confirmation before loading the file.
|
|
|
|
`page`
|
|
The page that the file will be loaded from. If None, the
|
|
current page is used.
|
|
|
|
`slot`
|
|
If True, `name` is taken to be a slot name, and `page` is ignored.
|
|
"""
|
|
|
|
alt = _("Delete slot [text]")
|
|
slot = None
|
|
|
|
def __init__(self, name, confirm=True, page=None, slot=False):
|
|
self.name = name
|
|
self.confirm = confirm
|
|
self.page = page
|
|
self.slot = slot
|
|
|
|
def __call__(self):
|
|
|
|
if not self.get_sensitive():
|
|
return
|
|
|
|
fn = __slotname(self.name, self.page, self.slot)
|
|
|
|
if self.confirm:
|
|
layout.yesno_screen(layout.DELETE_SAVE, FileDelete(self.name, False, self.page, self.slot))
|
|
return
|
|
|
|
renpy.unlink_save(fn)
|
|
|
|
def get_sensitive(self):
|
|
return renpy.can_load(__slotname(self.name, self.page, self.slot))
|
|
|
|
def get_selected(self):
|
|
return __newest_slot() == __slotname(self.name, self.page, self.slot)
|
|
|
|
|
|
def FileAction(name, page=None, **kwargs):
|
|
"""
|
|
:doc: file_action
|
|
|
|
"Does the right thing" with the file. This means loading it if the
|
|
load screen is showing (current screen is named "load"), and saving
|
|
otherwise.
|
|
|
|
`name`
|
|
The name of the slot to save to or load from. If None, an unused slot
|
|
(a large number based on the current time) will be used.
|
|
|
|
`page`
|
|
The page that the file will be saved to or loaded from. If None, the
|
|
current page is used.
|
|
|
|
Other keyword arguments are passed to FileLoad or FileSave.
|
|
"""
|
|
|
|
if renpy.current_screen().screen_name[0] == "load":
|
|
return FileLoad(name, page=page, **kwargs)
|
|
else:
|
|
return FileSave(name, page=page, **kwargs)
|
|
|
|
def _predict_file_page(page):
|
|
"""
|
|
Predicts the screenshots on `page`.
|
|
"""
|
|
|
|
if not config.predict_file_pages:
|
|
return
|
|
|
|
if page is None:
|
|
return
|
|
|
|
page = unicode(page)
|
|
|
|
for i in renpy.list_slots(page + "-"):
|
|
renpy.predict(renpy.slot_screenshot(i))
|
|
|
|
@renpy.pure
|
|
class FilePage(Action, DictEquality):
|
|
"""
|
|
:doc: file_action
|
|
|
|
Sets the file page to `page`, which should be one of "auto", "quick",
|
|
or an integer.
|
|
"""
|
|
|
|
def __init__(self, page):
|
|
self.page = str(page)
|
|
|
|
if page == "auto":
|
|
self.alt = _("File page auto")
|
|
elif page == "quick":
|
|
self.alt = _("File page quick")
|
|
else:
|
|
self.alt = _("File page [text]")
|
|
|
|
def __call__(self):
|
|
if not self.get_sensitive():
|
|
return
|
|
|
|
persistent._file_page = self.page
|
|
renpy.restart_interaction()
|
|
|
|
def get_selected(self):
|
|
return self.page == persistent._file_page
|
|
|
|
def predict(self):
|
|
_predict_file_page(self.page)
|
|
|
|
def FilePageName(auto="a", quick="q"):
|
|
"""
|
|
:doc: file_action_function
|
|
|
|
Returns the name of the current file page, as a string. If a normal
|
|
page, this returns the page number. Otherwise, it returns
|
|
`auto` or `quick`.
|
|
"""
|
|
|
|
page = persistent._file_page
|
|
|
|
if page == "quick":
|
|
return quick
|
|
elif page == "auto":
|
|
return auto
|
|
else:
|
|
return page
|
|
|
|
@renpy.pure
|
|
class FilePageNameInputValue(InputValue, DictEquality):
|
|
"""
|
|
:doc: input_value
|
|
|
|
An input value that updates the name of a file page.
|
|
|
|
`pattern`
|
|
This is used for the default name of a page. Python-style substition
|
|
is performed, such that {} is replaced with the number of the page.
|
|
|
|
`auto`
|
|
The name of the autosave page.
|
|
|
|
`quick`
|
|
The name of the quicksave page.
|
|
|
|
`page`
|
|
If given, the number of the page to display. This should usually
|
|
be left as None, to give the current page.
|
|
|
|
`default`
|
|
If true, this input can be editable by default.
|
|
"""
|
|
|
|
def __init__(self, pattern=_("Page {}"), auto=_("Automatic saves"), quick=_("Quick saves"), page=None, default=False):
|
|
|
|
self.pattern = pattern
|
|
self.auto = auto
|
|
self.quick = quick
|
|
|
|
self._page = page
|
|
|
|
self.default = default
|
|
|
|
def get_page(self):
|
|
if self._page is not None:
|
|
return self._page
|
|
else:
|
|
return persistent._file_page
|
|
|
|
@property
|
|
def editable(self):
|
|
page = self.get_page()
|
|
|
|
if page == "auto":
|
|
return False
|
|
elif page == "quick":
|
|
return False
|
|
|
|
return True
|
|
|
|
def get_text(self):
|
|
page = self.get_page()
|
|
|
|
if page == "auto":
|
|
return __(self.auto)
|
|
elif page == "quick":
|
|
return __(self.quick)
|
|
else:
|
|
|
|
page = int(page)
|
|
default = __(self.pattern).format(page)
|
|
rv = persistent._file_page_name.get(page, default)
|
|
|
|
if not rv.strip():
|
|
|
|
current, active = renpy.get_editable_input_value()
|
|
|
|
if not ((current is self) and active):
|
|
rv = default
|
|
|
|
return rv
|
|
|
|
def set_text(self, s):
|
|
|
|
page = self.get_page()
|
|
|
|
if page == "auto" or page =="quick":
|
|
return
|
|
|
|
default = __(self.pattern).format(page)
|
|
|
|
page = int(page)
|
|
|
|
fnp = persistent._file_page_name
|
|
|
|
if s == default:
|
|
fnp.pop(page, None)
|
|
else:
|
|
fnp[page] = s
|
|
|
|
def enter(self):
|
|
renpy.run(self.Disable())
|
|
raise renpy.IgnoreEvent()
|
|
|
|
|
|
def FileSlotName(slot, slots_per_page, auto="a", quick="q", format="%s%d"):
|
|
"""
|
|
:doc: file_action_function
|
|
|
|
Returns the name of the numbered slot. This assumes that slots on
|
|
normal pages are numbered in a linear order starting with 1, and
|
|
that page numbers start with 1. When slot is 2, and slots_per_page
|
|
is 10, and the other variables are the defaults:
|
|
|
|
* When the first page is showing, this returns "2".
|
|
* When the second page is showing, this returns "12".
|
|
* When the auto page is showing, this returns "a2".
|
|
* When the quicksave page is showing, this returns "q2".
|
|
|
|
`slot`
|
|
The number of the slot to access.
|
|
|
|
`slots_per_page`
|
|
The number of slots per page.
|
|
|
|
`auto`
|
|
A prefix to use for the auto page.
|
|
|
|
`quick`
|
|
A prefix to use for the quick page.
|
|
|
|
`format`
|
|
The formatting code to use. This is given two arguments: A string
|
|
giving the page prefix, and an integer giving the slot number.
|
|
"""
|
|
|
|
page = persistent._file_page
|
|
|
|
if page == "quick":
|
|
prefix = quick
|
|
page = 0
|
|
elif page == "auto":
|
|
prefix = auto
|
|
page = 0
|
|
else:
|
|
prefix = ""
|
|
page = int(page) - 1
|
|
|
|
return format % (prefix, page * slots_per_page + slot)
|
|
|
|
|
|
class FilePageNext(Action, DictEquality):
|
|
"""
|
|
:doc: file_action
|
|
|
|
Goes to the next file page.
|
|
|
|
`max`
|
|
If set, this should be an integer that gives the number of
|
|
the maximum file page we can go to.
|
|
|
|
`wrap`
|
|
If true, we can go to the first page when on the
|
|
last file page if `max` is set.
|
|
|
|
`auto`
|
|
If true and wrap is set, this can bring the player to
|
|
the page of automatic saves.
|
|
|
|
`quick`
|
|
If true and wrap is set, this can bring the player to
|
|
the page of automatic saves.
|
|
"""
|
|
|
|
alt = _("Next file page.")
|
|
|
|
def __init__(self, max=None, wrap=False, auto=True, quick=True):
|
|
|
|
page = persistent._file_page
|
|
|
|
if page == "auto":
|
|
if config.has_quicksave and quick:
|
|
page = "quick"
|
|
else:
|
|
page = "1"
|
|
|
|
elif page == "quick":
|
|
page = "1"
|
|
|
|
else:
|
|
page = int(page) + 1
|
|
|
|
if max is not None:
|
|
if page > max:
|
|
if wrap:
|
|
if config.has_autosave and auto:
|
|
page = "auto"
|
|
elif config.has_quicksave and quick:
|
|
page = "quick"
|
|
else:
|
|
page = "1"
|
|
else:
|
|
page = None
|
|
|
|
if page is not None:
|
|
page = str(page)
|
|
|
|
self.page = page
|
|
|
|
def __call__(self):
|
|
if not self.get_sensitive():
|
|
return
|
|
|
|
persistent._file_page = self.page
|
|
renpy.restart_interaction()
|
|
|
|
def get_sensitive(self):
|
|
return self.page is not None
|
|
|
|
def predict(self):
|
|
_predict_file_page(self.page)
|
|
|
|
|
|
class FilePagePrevious(Action, DictEquality):
|
|
"""
|
|
:doc: file_action
|
|
|
|
Goes to the previous file page, if possible.
|
|
|
|
`max`
|
|
If set, this should be an integer that gives the number of
|
|
the maximum file page we can go to. This is required to enable
|
|
wrap.
|
|
|
|
`wrap`
|
|
If true, we can go to the last page when on the first file page if max is set.
|
|
|
|
`auto`
|
|
If true, this can bring the player to
|
|
the page of automatic saves.
|
|
|
|
`quick`
|
|
If true, this can bring the player to
|
|
the page of automatic saves.
|
|
|
|
"""
|
|
|
|
alt = _("Previous file page.")
|
|
|
|
def __init__(self, max=None, wrap=False, auto=True, quick=True):
|
|
|
|
if wrap and max is not None:
|
|
max = str(max)
|
|
else:
|
|
max = None
|
|
|
|
page = persistent._file_page
|
|
|
|
if page == "auto":
|
|
page = max
|
|
|
|
elif page == "quick":
|
|
if config.has_autosave and auto:
|
|
page = "auto"
|
|
else:
|
|
page = max
|
|
|
|
elif page == "1":
|
|
if config.has_quicksave and quick:
|
|
page = "quick"
|
|
elif config.has_autosave and auto:
|
|
page = "auto"
|
|
else:
|
|
page = max
|
|
|
|
else:
|
|
page = str(int(page) - 1)
|
|
|
|
self.page = page
|
|
|
|
def __call__(self):
|
|
if not self.get_sensitive():
|
|
return
|
|
|
|
persistent._file_page = self.page
|
|
renpy.restart_interaction()
|
|
|
|
def get_sensitive(self):
|
|
return self.page
|
|
|
|
def predict(self):
|
|
_predict_file_page(self.page)
|
|
|
|
@renpy.pure
|
|
class FileTakeScreenshot(Action, DictEquality):
|
|
"""
|
|
:doc: file_action
|
|
|
|
Take a screenshot to be used when the game is saved. This can
|
|
be used to ensure that the screenshot is accurate, by taking
|
|
a picture of the screen before a file save screen is shown.
|
|
"""
|
|
|
|
def __call__(self):
|
|
renpy.take_screenshot()
|
|
renpy.restart_interaction()
|
|
|
|
@renpy.pure
|
|
def QuickSave(message=_("Quick save complete."), newest=False):
|
|
"""
|
|
:doc: file_action
|
|
|
|
Performs a quick save.
|
|
|
|
`message`
|
|
A message to display to the user when the quick save finishes.
|
|
|
|
`newest`
|
|
Set to true to mark the quicksave as the newest save.
|
|
"""
|
|
|
|
rv = [
|
|
FileSave(1, page="quick", confirm=False, cycle=True, newest=newest),
|
|
Notify(message),
|
|
]
|
|
|
|
rv[0].alt = _("Quick save.")
|
|
|
|
if not getattr(renpy.context(), "_menu", False):
|
|
rv.insert(0, FileTakeScreenshot())
|
|
|
|
return rv
|
|
|
|
@renpy.pure
|
|
def QuickLoad(confirm=True):
|
|
"""
|
|
:doc: file_action
|
|
|
|
Performs a quick load.
|
|
|
|
`confirm`
|
|
If true and not at the main menu, prompt for confirmation before loading the file.
|
|
"""
|
|
|
|
rv = FileLoad(1, page="quick", confirm=confirm, newest=False)
|
|
rv.alt = _("Quick load.")
|
|
return rv
|
|
|
|
init 1050 python hide:
|
|
|
|
if config.has_quicksave:
|
|
config.file_page_names.append("quick")
|
|
if config.has_autosave:
|
|
config.file_page_names.append("auto")
|
|
|
|
if persistent._file_page not in config.file_page_names:
|
|
try:
|
|
int(persistent._file_page)
|
|
except:
|
|
persistent._file_page = "1"
|
|
|