diff --git a/README.md b/README.md index b1c4260..bd39fab 100644 --- a/README.md +++ b/README.md @@ -3,19 +3,9 @@ CelestiaSunrise A savegame editor for the mobile game "My Little Pony" -``` -Required: -args==0.1.0 -clint==0.4.1 -docopt==0.6.2 -RapidXml==1.0.7 -requests==2.7.0 -six==1.9.0 -``` - Dependencies can be installed with the following command: ``` -> pip install -r requirements.txt +pip install -r requirements.txt ``` Basic usage: python CelestiaSunrise.py @@ -35,16 +25,17 @@ Linux Ezpz. ``` -> python setup.py install +python setup.py install ``` -Alternatively, you can specify the --user switch to install it locally, which doesn't require sudo privileges. -It will work regardless of your python version. +Alternatively, you can specify the --user switch to install it locally, which doesn't require sudo privileges. +It will work regardless of your python version. Windows ------------- * Grab the latest release executable. * Run it. +* ??? * Profit. Project Current State diff --git a/celestia/gui/currenciesframe.py b/celestia/gui/currenciesframe.py index 29f202f..fae525e 100644 --- a/celestia/gui/currenciesframe.py +++ b/celestia/gui/currenciesframe.py @@ -20,6 +20,7 @@ import Tkinter as tk import ttk from Tkconstants import N, S, E, W, NSEW +from .scrolledframe import ScrolledFrame from celestia.utility.tkvardescriptor import TkVarDescriptor, TkVarDescriptorOwner @six.add_metaclass(TkVarDescriptorOwner) @@ -42,16 +43,16 @@ def __init__(self, parent, text, value, limit, offset): self._limit.grid(row=offset, column=2, sticky=NSEW, **options) -class CurrenciesFrame(ttk.Frame): +class CurrenciesFrame(ScrolledFrame): def __init__(self, parent, xml_handle): - ttk.Frame.__init__(self, parent) + ScrolledFrame.__init__(self, parent) self._xml_handle = xml_handle self._currencies = defaultdict(dict) n = 0 for name, typ in xml_handle.currencies.items(): for cur, val in typ.items(): - self._currencies[name][cur] = CurrencyFrame(self, + self._currencies[name][cur] = CurrencyFrame(self.interior, cur, val.value, val.limit, n) diff --git a/celestia/gui/playerframe.py b/celestia/gui/playerframe.py new file mode 100644 index 0000000..6d7f984 --- /dev/null +++ b/celestia/gui/playerframe.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# File: playerframe.py +# by Arzaroth Lekva +# arzaroth@arzaroth.com +# + +from __future__ import print_function, absolute_import, unicode_literals + +import six +try: + # py3 + import tkinter as tk + import tkinter.ttk as ttk + from tkinter.constants import N, S, E, W, NSEW +except ImportError: + # py2 + import Tkinter as tk + import ttk + from Tkconstants import N, S, E, W, NSEW +from celestia.gui.currenciesframe import CurrencyFrame + +class PlayerFrame(ttk.Frame): + def __init__(self, parent, xml_handle): + ttk.Frame.__init__(self, parent, height=400) + self.grid_propagate(0) + + self._xml_handle = xml_handle + self._player_infos = {} + for n, (name, typ) in enumerate(xml_handle.player_infos.items()): + self._player_infos[name] = CurrencyFrame(self, name, typ.value, + typ.limit, n) + + def commit(self): + for name, typ in self._xml_handle.player_infos.items(): + typ.value = self._player_infos[name].value diff --git a/celestia/gui/ponygui.py b/celestia/gui/ponygui.py index c8eeb03..1d2ac4e 100644 --- a/celestia/gui/ponygui.py +++ b/celestia/gui/ponygui.py @@ -32,6 +32,7 @@ from .basegui import BaseGui from .missingponiesframe import MissingPoniesFrame from .currenciesframe import CurrenciesFrame +from .playerframe import PlayerFrame from .poniesframe import PoniesFrame from .zonesframe import ZonesFrame from .threaded import ThreadedLoad, ThreadedSave @@ -70,7 +71,10 @@ def success_callback(res): success_callback, self._unload) def _export_xml(self): - filename = asksaveasfilename() + filename = asksaveasfilename(defaultextension='.xml', + filetypes=[('XML files', '.xml'), + ('All files', '*')], + parent=self) if filename: loadingbox = LoadingDialog(self) queue = Queue() @@ -86,7 +90,10 @@ def _export_xml(self): self, queue, loadingbox) def _import_xml(self): - filename = askopenfilename() + filename = askopenfilename(defaultextension='.xml', + filetypes=[('XML files', '.xml'), + ('All files', '*')], + parent=self) if filename: self.withdraw() loadingbox = LoadingDialog(self, False) @@ -129,6 +136,8 @@ def _create_widgets(self): def _create_frames(self): BaseGui._create_frames(self) self._notebook = ttk.Notebook(self._main_frame) + self._player_frame = PlayerFrame(self._main_frame, + self._xml_handle) self._currencies_frame = CurrenciesFrame(self._main_frame, self._xml_handle) self._zones_frame = ZonesFrame(self._main_frame, @@ -137,6 +146,8 @@ def _create_frames(self): self._xml_handle) self._missing_ponies_frame = MissingPoniesFrame(self._main_frame, self._xml_handle) + self._notebook.add(self._player_frame, + text="Player") self._notebook.add(self._currencies_frame, text="Currencies") self._notebook.add(self._ponies_frame, @@ -160,6 +171,7 @@ def _grid_widgets(self): self._save_button.grid(row=2, column=0, sticky=NSEW, padx=3, pady=4) def _commit(self): + self._player_frame.commit() self._currencies_frame.commit() self._ponies_frame.commit() self._zones_frame.commit() diff --git a/celestia/gui/zonesframe.py b/celestia/gui/zonesframe.py index cb7820b..e754b53 100644 --- a/celestia/gui/zonesframe.py +++ b/celestia/gui/zonesframe.py @@ -19,6 +19,7 @@ import Tkinter as tk import ttk from Tkconstants import N, S, E, W, NSEW +from .scrolledframe import ScrolledFrame from celestia.utility.tkvardescriptor import TkVarDescriptor, TkVarDescriptorOwner @six.add_metaclass(TkVarDescriptorOwner) @@ -68,16 +69,16 @@ def update(self): "s" if len(self.zone.shops) > 1 else "")) -class ZonesFrame(ttk.Frame): +class ZonesFrame(ScrolledFrame): def __init__(self, parent, xml_handle): - ttk.Frame.__init__(self, parent) + ScrolledFrame.__init__(self, parent) self._xml_handle = xml_handle self._zones = {} reset_offset = len(self._xml_handle.zones) * 2 - ttk.Label(self).grid(row=reset_offset, column=0) + ttk.Label(self.interior).grid(row=reset_offset, column=0) for n, (ID, zone) in enumerate(self._xml_handle.zones.items()): - self._zones[ID] = ZoneFrame(self, zone, n, reset_offset + 1) + self._zones[ID] = ZoneFrame(self.interior, zone, n, reset_offset + 1) def commit(self): for ID, zone in self._xml_handle.zones.items(): diff --git a/celestia/shell/ponyshell.py b/celestia/shell/ponyshell.py index aa9b2a5..403097a 100644 --- a/celestia/shell/ponyshell.py +++ b/celestia/shell/ponyshell.py @@ -20,10 +20,11 @@ from celestia.utility.gluid import retrieve_gluid from celestia.utility.version import check_version from .docopt_utils import docopt_cmd, docopt_cmd_completion -from .show import (show_currencies, show_currency, +from .show import (show_player, + show_currencies, show_currency, show_ponies, show_pony, show_zones, show_zone) -from .set import (set_currency, +from .set import (set_player, set_currency, set_ponies, set_pony, set_zones, set_zone, set_inventory) @@ -52,6 +53,7 @@ def __init__(self, savedata): self._xml_handle.pre_load() self.savedata = savedata self._show_functions = { + 'player': show_player, 'currencies': show_currencies, 'currency': show_currency, 'ponies': show_ponies, @@ -60,6 +62,7 @@ def __init__(self, savedata): 'zone': show_zone, } self._set_functions = { + 'player': set_player, 'currency': set_currency, 'ponies': set_ponies, 'pony': set_pony, @@ -81,6 +84,7 @@ def do_show(self, args): """Show what you requested. Usage: + show player [] show currencies show currency ... show ponies [-i|-o] @@ -89,6 +93,7 @@ def do_show(self, args): show zone ... Arguments: + player_data Id of a player_data item. Can be retrieved with "show player". currency_id Id of a currency. Can be retrieved with "show currencies". pony_id Id of a pony. Can be retrieved with "show ponies". zone_id Id of a zone. Can be retrieved with "show zones". @@ -107,6 +112,7 @@ def do_set(self, args): """Set what you requested. Usage: + set player set currency ... set ponies (level|shards) (up|down) set ponies (level|shards) @@ -121,6 +127,7 @@ def do_set(self, args): set inventory add ... Arguments: + player_data Id of a player_data item. Can be retrieved with "show player". currency_id Id of a currency. Can be retrieved with "show currencies". pony_id Id of a pony. Can be retrieved with "show ponies". zone_id Id of a zone. Can be retrieved with "show zones". diff --git a/celestia/shell/set.py b/celestia/shell/set.py index f1e8e4b..a8f13a9 100644 --- a/celestia/shell/set.py +++ b/celestia/shell/set.py @@ -8,6 +8,14 @@ from __future__ import print_function, absolute_import, unicode_literals +def set_player(xml_handle, args): + for typ in xml_handle.player_infos.values(): + if args[''] == typ.name: + try: + typ.value = args[''] + except ValueError as e: + print(str(e)) + def set_currency(xml_handle, args): for currency_id in args['']: for typ in xml_handle.currencies.values(): diff --git a/celestia/shell/show.py b/celestia/shell/show.py index 72bd354..28d59d1 100644 --- a/celestia/shell/show.py +++ b/celestia/shell/show.py @@ -8,6 +8,11 @@ from __future__ import print_function, absolute_import, unicode_literals +def show_player(xml_handle, args): + for typ in xml_handle.player_infos.values(): + if not args[''] or args[''] == typ.name: + print(typ) + def show_currencies(xml_handle, args): for name, typ in xml_handle.currencies.items(): print('{}:'.format(name)) diff --git a/celestia/utility/ponies.py b/celestia/utility/ponies.py index 5859bc0..439a27d 100644 --- a/celestia/utility/ponies.py +++ b/celestia/utility/ponies.py @@ -37,26 +37,28 @@ ('Pony_Big_Mac', 'Big Macintosh'), ('Pony_Blue_moon', 'Blue Moon'), ('Pony_Bon_Bon', 'Bon Bon'), + ('Pony_Braeburn', 'Braeburn'), ('Pony_Bright_Unicorn', 'Bright Unicorn'), ('Pony_Bulk_Biceps', 'Bulk Biceps'), - ('Pony_Braeburn', 'Braeburn'), ('Pony_Candy_Apples', 'Candy Apples'), ('Pony_Caramel', 'Caramel'), ('Pony_Caramel_Apple', 'Caramel Apple'), ('Pony_Cheerilee', 'Cheerilee'), ('Pony_Cheese_Sandwich', 'Cheese Sandwich'), - ('Pony_CherryBerry', 'Cherry Berry'), ('Pony_Cherry_Fizzy', 'Cherry Fizzy'), ('Pony_Cherry_Jubilee', 'Cherry Jubilee'), + ('Pony_CherryBerry', 'Cherry Berry'), ('Pony_Claude_the_Puppeteer', 'Claude the Puppeteer'), ('Pony_Clear_Skies', 'Clear Skies'), + ('Pony_Clumsy_Clownspony', 'Clumsy Clownspony'), ('Pony_Coco_Pommel', 'Coco Pommel'), ('Pony_Comet_Tail', 'Comet Tail'), ('Pony_Compass_Star', 'Compass Star'), ('Pony_Conductor', 'Conductor'), - ('Pony_Curio_Shopkeeper', 'Curio Shopkeeper'), ('Pony_Crescent_Moon', 'Crescent Moon'), + ('Pony_Curio_Shopkeeper', 'Curio Shopkeeper'), ('Pony_Daisy', 'Daisy'), + ('Pony_Dancing_Clownspony', 'Dancing Clownspony'), ('Pony_Daring', 'Daring Do'), ('Pony_Diamond_Tiara', 'Diamond Tiara'), ('Pony_Discord', 'Discord'), @@ -86,23 +88,32 @@ ('Pony_Four_Step', 'Four Step'), ('Pony_Frederic', 'Frederic'), ('Pony_Gala_Appleby', 'Gala Appleby'), + ('Pony_Gilda', 'Gilda'), + ('Pony_Gleeful_Clownspony', 'Gleeful Clownspony'), ('Pony_Golden_Delicious', 'Golden Delicious'), ('Pony_Golden_Harvest', 'Golden Harvest'), ('Pony_Goldie_Delicious', 'Goldie Delicious'), ('Pony_Goth_Unicorn', 'Goth Unicorn'), + ('Pony_Grampa_Gruff', 'Grampa Gruff'), ('Pony_Granny_Smith', 'Granny Smith'), ('Pony_Green_Jewel', 'Green Jewel'), + ('Pony_Greta', 'Greta'), + ('Pony_Griffon_Shopkeeper', 'Griffon Shopkeeper'), ('Pony_Half_Baked_Apple', 'Half Baked Apple'), ('Pony_Hayseed_Turnip_Truck', 'Hayseed Turnip Truck'), ('Pony_Hoity_Toity', 'Hoity Toity'), ('Pony_Jeff_Letrotski', 'Jeff Letrotski'), ('Pony_Jet_Set', 'Jet Set'), + ('Pony_Jigging_Clownspony', 'Jigging Clownspony'), ('Pony_Joe', 'Joe'), + ('Pony_Jokester_Clownspony', 'Jokester Clownspony'), ('Pony_Junebug', 'Junebug'), ('Pony_Junior_Deputy', 'Junior Deputy'), ('Pony_King_Sombra', 'King Sombra'), + ('Pony_Lassoing_Clownspony', 'Lassoing Clownspony'), ('Pony_Lemon_Hearts', 'Lemon Hearts'), ('Pony_Lemony_Gem', 'Lemony Gem'), + ('Pony_Li_I_Griffon', 'Li\'l Griffon'), ('Pony_Lightning_Dust', 'Lightning Dust'), ('Pony_Lily_Valley', 'Lily Valley'), ('Pony_Limestone_Pie', 'Limestone Pie'), @@ -115,6 +126,7 @@ ('Pony_Lyrica', 'Lyrica'), ('Pony_Magnum', 'Hondo Flanks (Magnum)'), ('Pony_Mane_iac', 'Mane-iac'), + ('Pony_Manehattan_Delegate', 'Manehattan Delegate'), ('Pony_Marble_Pie', 'Marble Pie'), ('Pony_Maud_Pie', 'Maud Pie'), ('Pony_Mayor', 'Mayor'), @@ -124,6 +136,7 @@ ('Pony_Mr_Cake', 'Mr. Cake'), ('Pony_Mrs_Cake', 'Mrs. Cake'), ('Pony_MsHarshwhinny', 'Ms. Harshwhinny'), + ('Pony_Musical_Clownspony', 'Musical Clownspony'), ('Pony_Neon_Lights', 'Neon Lights'), ('Pony_Nerdpony', 'Nerdpony'), ('Pony_Night_Glider', 'Night Glider'), @@ -179,6 +192,7 @@ ('Pony_Spitfire', 'Spitfire'), ('Pony_Sprinkle_Stripe', 'Sprinkle Stripe'), ('Pony_Starlight_Glimmer', 'Starlight Glimmer'), + ('Pony_Studious_Delegate', 'Studious Delegate'), ('Pony_Sugar_Belle', 'Sugar Belle'), ('Pony_Sunny_Daze', 'Sunny Daze'), ('Pony_Sunsetshimmer', 'Sunset Shimmer'), @@ -204,10 +218,12 @@ ('Pony_Twist', 'Twist'), ('Pony_Uncle_Orange', 'Uncle Orange'), ('Pony_Unicorn_Guard', 'Unicorn Guard'), + ('Pony_Unicorn_Painter', 'Unicorn Painter'), ('Pony_Uppercrust', 'Upper Crust'), ('Pony_Walter', 'Walter (Bowling Pony)'), ('Pony_Wensley', 'Wensley'), + ('Pony_Whinnyapolis_Delegate', 'Whinnyapolis Delegate'), ('Pony_Wild_Fire', 'Wild Fire'), ('Pony_Zecora', 'Zecora'), - ('Pony_Zipporwhill', 'Zipporwhill'), + ('Pony_Zipporwhill', 'Zipporwhill') ]) diff --git a/celestia/utility/utility.py b/celestia/utility/utility.py index bbb8102..87e5a56 100644 --- a/celestia/utility/utility.py +++ b/celestia/utility/utility.py @@ -249,6 +249,8 @@ def __init__(self, name, real_name, tag, limit=None): self.real_name = real_name self.limit = limit self._tag = tag[name] + if self.limit is not None and self.value > self.limit: + self.value = self.limit @property def value(self): @@ -272,6 +274,10 @@ def __repr__(self): self.limit)) +class PlayerData(Currency): + pass + + class Clearables(object): def __init__(self, ID, tag): self.ID = ID diff --git a/celestia/xml/xmlhandler.py b/celestia/xml/xmlhandler.py index b291a58..3604406 100644 --- a/celestia/xml/xmlhandler.py +++ b/celestia/xml/xmlhandler.py @@ -15,7 +15,7 @@ from celestia.utility import PONY_LIST from celestia.utility.defaultordereddict import DefaultOrderedDict from celestia.utility.utility import (Pony, Inventory, MissingPonies, - Currency, Clearables, + Currency, PlayerData, Clearables, Foes, Zone, Shops) class XmlDescriptor(object): @@ -42,6 +42,7 @@ class XmlHandler(object): inventory = XmlDescriptor() missing_ponies = XmlDescriptor() currencies = XmlDescriptor() + player_infos = XmlDescriptor() actions = XmlDescriptor() zones = XmlDescriptor() _mapzones = XmlDescriptor() @@ -144,6 +145,18 @@ def _get_currencies(self): pass return res + def _get_player_infos(self): + playerdata = self.xmlobj['MLP_Save']['PlayerData'] + res = OrderedDict() + res['Level'] = PlayerData('@Level', 'Level', playerdata, 120) + res['XP'] = PlayerData('@XP', 'XP', playerdata) + try: + # VIP Update (2.7) + res['VIP Points'] = PlayerData('@vip_points', 'VIP Points', playerdata['vip']) + except: + pass + return res + def _get_zones(self): mapzones_spec = OrderedDict(( ("0", {"name": "Ponyville", @@ -204,6 +217,7 @@ def populate_dict(dikt, key='@ID', suffix='', inner=None): return {'Global': glob, 'Ponies': actions} def pre_load(self): + self.player_infos self.currencies self.ponies self.inventory diff --git a/setup.py b/setup.py index ceb8eaf..5a49cc5 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ import os from setuptools import setup, find_packages -VERSION = ("v1", "3", "0") +VERSION = ("v1", "4", "0") if __name__ == '__main__': setup(