瀏覽代碼

Save/Load implemented.

All data can be saved (although some of it can't be retrieved yey and placeholders are in use). The save menu is implemented and games can be saved from there and loaded from the begin menu (but loading a game in arbitrary maps has it's own problems).
Iñigo Valentin 3 年之前
父節點
當前提交
56a8eae34a

+ 1 - 1
README.md

@@ -27,7 +27,7 @@ Note that, while these are actual screenshots of V-Gears, none of the images, sp
 |**Items**|**Key Items**|**Equip**|
 |[<img src="https://v-gears.inigovalentin.com/img/screenshot/item_menu.png" alt="Item Menu" width="250"/>](https://v-gears.inigovalentin.com/img/screenshot/item_menu.png "Item Menu")|[<img src="https://v-gears.inigovalentin.com/img/screenshot/item_menu_key.png" alt="Key items menuy" width="250"/>](https://v-gears.inigovalentin.com/img/screenshot/item_menu_key.png "Key items menu")|[<img src="https://v-gears.inigovalentin.com/img/screenshot/equip_menu.png" alt="Equip Menu" width="250"/>](https://v-gears.inigovalentin.com/img/screenshot/equip_menu.png "Equip Menu")|
 |**Materia**|||
-|[<img src="https://v-gears.inigovalentin.com/img/screenshot/materia_menu.png" alt="Materia Menu" width="250"/>](https://v-gears.inigovalentin.com/img/screenshot/materia_menu.png "Materia Menu")|||
+|[<img src="https://v-gears.inigovalentin.com/img/screenshot/materia_menu.png" alt="Materia Menu" width="250"/>](https://v-gears.inigovalentin.com/img/screenshot/materia_menu.png "Materia Menu")|[<img src="https://v-gears.inigovalentin.com/img/screenshot/save_menu.png" alt="Save Menu" width="250"/>](https://v-gears.inigovalentin.com/img/screenshot/save_menu.png "Save Menu")||
 
 ### Installer:
 |**Installer**|**Advanced**|

+ 1 - 1
V-Gears-Installer/include/decompiler/field/instruction/FieldWindowInstruction.h

@@ -43,7 +43,7 @@ class FieldWindowInstruction : public KernelCallInstruction{
 
         void ProcessMESSAGE(CodeGenerator* code_gen, const std::string& script_name);
 
-        void ProcessMPNAM(CodeGenerator* code_gen);
+        void ProcessMPNAM(CodeGenerator* code_gen, const std::string& script_name);
 
 
         /**

+ 2 - 2
V-Gears-Installer/src/decompiler/field/instruction/FieldWindowInstruction.cpp

@@ -39,7 +39,7 @@ void FieldWindowInstruction::ProcessInst(
         case OPCODES::MESSAGE: ProcessMESSAGE(code_gen, eng.GetScriptName()); break;
         case OPCODES::MPARA: code_gen->WriteTodo(md.GetEntityName(), "MPARA"); break;
         case OPCODES::MPRA2: code_gen->WriteTodo(md.GetEntityName(), "MPRA2"); break;
-        case OPCODES::MPNAM: ProcessMPNAM(code_gen); break;
+        case OPCODES::MPNAM: ProcessMPNAM(code_gen, eng.GetScriptName()); break;
         case OPCODES::ASK: code_gen->WriteTodo(md.GetEntityName(), "ASK"); break;
         case OPCODES::MENU: ProcessMENU(code_gen); break;
         case OPCODES::MENU2: ProcessMENU2(code_gen); break;
@@ -154,7 +154,7 @@ void FieldWindowInstruction::ProcessWCLSE(CodeGenerator* code_gen){
     code_gen->AddOutputLine((boost::format("dialog:dialog_close(\"%1%\")") % windowId).str());
 }
 
-void FieldWindowInstruction::ProcessMPNAM(CodeGenerator* code_gen){
+void FieldWindowInstruction::ProcessMPNAM(CodeGenerator* code_gen, const std::string& script_name){
     code_gen->AddOutputLine((
       boost::format("dialog:set_map_name(%1%_%2%)") % script_name % params_[0]->GetUnsigned()
     ).str());

+ 519 - 47
V-Gears/include/core/Savemap.h

@@ -328,68 +328,540 @@ class Savemap{
         bool IsEmpty();
 
         /**
-         * Generates a string with all the required data to generate a preview of the savemap.
+         * Retrieves the control key .
          *
-         * The included information contains the following fields, separated by the character "#":
-         * - Slot
-         * - Control key
-         * - Party money
-         * - Game time (in seconds)
-         * - Location text
-         * - Party member 1 name
-         * - Party member 1 level
-         * - Party member 1 character ID.
-         * - Party member 2 character ID.
-         * - Party member 3 character ID.
+         * @return The control key of the slot.
+         */
+        std::string GetControlKey();
+
+        /**
+         * Retrieves a colour component from a window corner.
+         *
+         * @param[in] corner The window corner. See {@see Corner}.
+         * @param[in] corner The color component to get. See {@see Colour}.
+         * @return The color component of the specified corner of windows. If an invalid slot is
+         * specified, or if the slot is empty, or if an invalid corner or color are requested, 0.
+         */
+        unsigned int GetWindowCornerColourComponent(
+          const unsigned int corner, const unsigned int comp
+        );
+
+        /**
+         * Retrieves the money.
+         *
+         * @return The money of the slot.
+         */
+        unsigned int GetMoney();
+
+        /**
+         * Retrieves the total playtime.
+         *
+         * @param[in] slot The slot to read from.
+         * @return The total playtime, in seconds.
+         */
+        unsigned int GetGameTime();
+
+        /**
+         * Retrieves the time in the timer.
+         *
+         * @return The timer time, in seconds. If there is no timer saved, 0.
+         */
+        unsigned int GetCountdownTime();
+
+        /**
+         * Retrieves the ID of a party member.
+         *
+         * @param[in] pos Position in the party.
+         * @return The ID of the character at the requested position. If there is no character at
+         * the requested position, -1.
+         */
+        int GetPartyMember(const unsigned int pos);
+
+        /**
+         * Retrieves the ID of an item in the inventory.
+         *
+         * @param[in] pos Position in the inventory.
+         * @return The ID of the item at the requested inventory position. If there is no item at
+         * the requested position, 0.
+         */
+        unsigned int GetItemAtPosId(const unsigned int pos);
+
+        /**
+         * Retrieves the quantity of an item in the inventory.
+         *
+         * @param[in] pos Position in the inventory.
+         * @return The quantity of the item at the requested inventory position. If there is no
+         * item at the requested position, 0.
+         */
+        unsigned int GetItemAtPosQty(const unsigned int pos);
+
+        /**
+         * Checks if a key item is owned.
+         *
+         * @param[in] id Key item ID.
+         * @return True if the key item is owned, false if not. If an invalid id is passed, false.
+         */
+        bool GetKeyItem(const unsigned int id);
+
+        /**
+         * Retrieves the ID of a materia in the inventory.
+         *
+         * @param[in] pos Position in the materia inventory.
+         * @return The ID of the materia at the requested inventory position. If an invalid
+         * position is passed, or if there is no materia at the requested position, -1.
+         */
+        int GetMateriaAtPosId(const unsigned int pos);
+
+        /**
+         * Retrieves the AP of a materia in the inventory.
+         *
+         * @param[in] pos Position in the materia inventory.
+         * @return The AP of the materia at the requested inventory position. If an invalid
+         * position is passed, or if there is no materia at the requested position, 0.
+         */
+        unsigned int GetMateriaAtPosAp(const unsigned int pos);
+
+        /**
+         * Checks if there is an Enemy Skill materia at a inventory position.
+         *
+         * @param[in] pos Position in the materia inventory.
+         * @return True if the materia in the specified position is an Enemy Skill materia, false
+         * if not. If an invalid position is passed, or if there is no materia at that position,
+         * false.
+         */
+        bool IsMateriaAtPosESkill(const unsigned int pos);
+
+        /**
+         * Checks if a a enemy skill is learned by a materia in the inventory.
+         *
+         * @param[in] pos Position in the materia inventory.
+         * @param[in] skill Skill ID, starting from 0.
+         * @return True if the materia in the specified position exists, is an Enemy Skill materia
+         * and has learned the specified skill. False in any other case.
+         */
+        bool IsMateriaAtPosESkillLearned(const unsigned int pos, const unsigned int skill);
+
+        /**
+         * Retrieves the ID of a materia in the stash.
+         *
+         * @param[in] pos Position in the materia stash.
+         * @return The ID of the materia at the requested stahs position. If an invalid
+         * position is passed, or if there is no materia at the requested position, -1.
+         */
+        int GetStashAtPosId(const unsigned int pos);
+
+        /**
+         * Retrieves the AP of a materia in the stash.
+         *
+         * @param[in] pos Position in the materia stash.
+         * @return The AP of the materia at the requested inventory position. If an invalid
+         * position is passed, or if there is no materia at the requested position, 0.
+         */
+        unsigned int GetStashAtPosAp(const unsigned int pos);
+
+        /**
+         * Checks if there is an Enemy Skill materia at a stash position.
+         *
+         * @param[in] pos Position in the materia stash.
+         * @return True if the materia in the specified position is an Enemy Skill materia, false
+         * if not. If an invalid position is passed, or if there is no materia at that position,
+         * false.
+         */
+        bool IsStashAtPosESkill(const unsigned int pos);
+
+        /**
+         * Checks if a a enemy skill is learned by a materia in the stash.
+         *
+         * @param[in] pos Position in the materia stash.
+         * @param[in] skill Skill ID, starting from 0.
+         * @return True if the materia in the specified position exists, is an Enemy Skill materia
+         * and has learned the specified skill. False in any other case.
+         */
+        bool IsStashAtPosESkillLearned(const unsigned int pos, const unsigned int skill);
+
+        /**
+         * Retrieves the X coordinate of the player.
+         *
+         * @return The X coordinate.
+         */
+        unsigned int GetLocationX();
+
+        /**
+         * Retrieves the Y coordinate of the player.
+         *
+         * @return The Y coordinate.
+         */
+        unsigned int GetLocationY();
+
+        /**
+         * Retrieves the Z coordinate of the player.
+         *
+         * @return The Z coordinate. If it was not saved, -1.
+         */
+        int GetLocationZ();
+
+        /**
+         * Retrieves the walkmesh triangle of the player.
+         *
+         * @return The triangle ID.
+         */
+        unsigned int GetLocationTriangle();
+
+        /**
+         * Retrieves the facing angle of the player.
+         *
+         * @param[in] slot The slot to read from.
+         * @return The angle.
+         */
+        int GetLocationAngle();
+
+        /**
+         * Retrieves the field ID.
+         *
+         * @return The field ID. If the savemap is saved in the worldmap, an empty string.
+         */
+        std::string GetLocationField();
+
+        /**
+         * Retrieves the location name.
+         *
+         * @return The location name to be displayed in the save slot. If the location name has not
+         * been saved, an empty string.
+         */
+        std::string GetLocationName();
+
+        /**
+         * Retrieves a setting.
+         *
+         * @param[in] key Setting key.
+         * @return The setting value.
+         * @todo Implement and document properly.
+         */
+        int GetSetting(const unsigned int key);
+
+        /**
+         * Retrieves the char ID of a character.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] id The character ID.
+         * @return The char ID of the character. If an invalid id is passed, or if the character
+         * doesn't have a char ID, -1.
+         */
+        int GetCharacterCharId(const unsigned int id);
+
+        /**
+         * Retrieves the name of a character.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] id The character ID.
+         * @return The name of the character. If an invalid id is passed, an empty string.
+         */
+        std::string GetCharacterName(const unsigned int id);
+
+        /**
+         * Retrieves the level of a character.
+         *
+         * @param[in] id The character ID.
+         * @return The level of the character. If an invalid id is passed, 1.
+         */
+        unsigned int GetCharacterLevel(const unsigned int id);
+
+        /**
+         * Retrieves the total kills of a character.
+         *
+         * @param[in] id The character ID.
+         * @return The kills of the character. If an invalid id is passed, 0.
+         */
+        unsigned int GetCharacterKills(const unsigned int id);
+
+        /**
+         * Checks if a character is enabled.
+         *
+         * @param[in] id The character ID.
+         * @return True if the character is enabled, false if not. If an invalid id is passed,
+         * false.
+         */
+        bool IsCharacterEnabled(const unsigned int id);
+
+        /**
+         * Checks if a character is locked in or out of the party
+         *
+         * @param[in] id The character ID.
+         * @return True if the character is enabled, false if not. If an invalid id is passed,
+         * false.
+         */
+        bool IsCharacterLocked(const unsigned int id);
+
+        /**
+         * Checks the row of a character.
+         *
+         * @param[in] id The character ID.
+         * @return True if the character is in the back row, false if not. If an invalid id is
+         * passed, false.
+         */
+        bool IsCharacterBackRow(const unsigned int id);
+
+        /**
+         * Retrieves the total experience of a character.
+         *
+         * @param[in] id The character ID.
+         * @return The experience of the character. If an invalid id is passed, 0.
+         */
+        unsigned int GetCharacterExp(const unsigned int id);
+
+        /**
+         * Retrieves the experience for next level of a character.
+         *
+         * @param[in] id The character ID.
+         * @return The experience of the character. If an invalid id is passed, 0.
+         */
+        unsigned int GetCharacterExpToNext(const unsigned int id);
+
+        /**
+         * Retrieves the current limit level of a character from a saved savemap.
+         *
+         * @param[in] id The character ID.
+         * @return The limit level of the character. If an invalid id is passed, 0.
+         */
+        unsigned int GetCharacterLimitLevel(const unsigned int id);
+
+        /**
+         * Retrieves the current limit bar status level of a character.
+         *
+         * @param[in] id The character ID.
+         * @return The limit bar status of the character. If an invalid id is passed, 0.
+         */
+        unsigned int GetCharacterLimitBar(const unsigned int id);
+
+        /**
+         * Retrieves the ID of the weapon of a character.
+         *
+         * @param[in] id The character ID.
+         * @return The character's weapon ID. If an invalid id is passed, 0.
+         */
+        unsigned int GetCharacterWeaponId(const unsigned int id);
+
+        /**
+         * Retrieves the ID of the armor of a character.
+         *
+         * @param[in] id The character ID.
+         * @return The character's armor ID. If an invalid id is passed, 0.
+         */
+        unsigned int GetCharacterArmorId(const unsigned int id);
+
+        /**
+         * Retrieves the ID of the weapon of a character.
+         *
+         * @param[in] id The character ID.
+         * @return The character's weapon ID. If an invalid id is passed, or if the characetr has
+         * no accessory, -1.
+         */
+        int GetCharacterAccessoryId(const unsigned int id);
+
+        /**
+         * Retrieves the base value of a stat of a character.
+         *
+         * @param[in] id The character ID.
+         * @param[in] stat The stat ID (see {@see STAT}).
+         * @return The base value of the specified stat. If an invalid id or stat is passed, 0.
+         */
+        unsigned int GetCharacterStatBase(const unsigned int id, const unsigned int stat);
+
+        /**
+         * Retrieves the extra value of a stat of a character.
+         *
+         * For HP and MP, the extra value means the current value. For any other stat, the bonus
+         * gained by using sources.
+         *
+         * @param[in] id The character ID.
+         * @param[in] stat The stat ID (see {@see Savemap::STAT}).
+         * @return The extra value of the specified stat. If an invalid id or stat is passed, 0.
+         */
+        unsigned int GetCharacterStatExtra(const unsigned int id, const unsigned int stat);
+
+        /**
+         * Retrieves the uses of a character's limit level.
+         *
+         * @param[in] id The character ID.
+         * @param[in] level The limit level.
+         * @return Number of uses of the techniques in the specified limit level. If an invalid id
+         * or limit level is passed, 0.
+         */
+        unsigned int GetCharacterLimitUses(const unsigned int id, const unsigned int level);
+
+        /**
+         * Checks if a limit technique is learned by a character.
+         *
+         * @param[in] id The character ID.
+         * @param[in] level The limit level.
+         * @param[in] tech The technique position in the level.
+         * @return True if the technique has been learned, false if not. If an invalid id, limit
+         * level or technique is passed, 0.
+         */
+        bool IsCharacterLimitLearned(
+          const unsigned int id, const unsigned int level, const unsigned int tech
+        );
+
+        /**
+         * Retrieves the ID of an equipped materia.
+         *
+         * @param[in] id The character ID.
+         * @param[in] weapon If false, check materia equipped in the weapon. If false, check
+         * materia equiped in the armor.
+         * @param[in] pos Position in the equipment slots.
+         * @return The ID of the equipped materia. Id or position is passed, or if there is no
+         * materia at the requested position, -1.
+         */
+        int GetCharacterMateriaId(const unsigned int id, const bool weapon, const unsigned int pos);
+
+        /**
+         * Retrieves the AP of an equipped materia.
+         *
+         * @param[in] id The character ID.
+         * @param[in] weapon If false, check materia equipped in the weapon. If false, check
+         * materia equiped in the armor.
+         * @param[in] pos Position in the equipment slots.
+         * @return The AP of the equipped materia. If an invalid id or position is passed, or if
+         * there is no materia at the requested position, 0.
+         */
+        unsigned int GetCharacterMateriaAp(
+          const unsigned int id, const bool weapon, const unsigned int pos
+        );
+
+        /**
+         * Checks if an equipped materia is Enemy Skill.
+         *
+         * @param[in] id The character ID.
+         * @param[in] weapon If false, check materia equipped in the weapon. If false, check
+         * materia equiped in the armor.
+         * @param[in] pos Position in the equipment slots.
+         * @return True if the materia in the specified position is an Enemy Skill materia, false
+         * if not. If an invalid position is passed, or if there is no materia at that position,
+         * false.
+         */
+        bool IsCharacterMateriaESkill(const unsigned int id, const bool weapon, const unsigned int pos);
+
+        /**
+         * Checks if a a enemy skill is learned by a equipped materia.
+         *
+         * @param[in] id The character ID.
+         * @param[in] weapon If false, check materia equipped in the weapon. If false, check
+         * materia equiped in the armor.
+         * @param[in] pos Position in the equipment slots.
+         * @param[in] skill Skill ID, starting from 0.
+         * @return True if the materia in the specified position exists, is an Enemy Skill materia
+         * and has learned the specified skill. False in any other case.
+         */
+        bool IsCharacterMateriaESkillLearned(
+          const unsigned int id, const bool weapon, const unsigned int pos, const unsigned int skill
+        );
+
+        /**
+         * Retrieves the value of a bank address.
          *
-         * @return The generated string.
+         * @param[in] bank The bank ID.
+         * @param[in] address The address in the bank.
+         * @return The value. If an invalid bank or address level is passed, 0.
          */
-        std::string GetPreviewData();
+        int GetData(const unsigned int bank, const unsigned int address);
 
         /**
          * Character basic stats.
          */
-        enum class STAT{
+        class STAT{
 
-            /**
-             * Strength stat.
-             */
-            STR,
+            public:
 
-            /**
-             * Vtatlity stat.
-             */
-            VIT,
+                /**
+                 * Strength stat.
+                 */
+                static const unsigned int STR = 0;
 
-            /**
-             * Magic stat.
-             */
-            MAG,
+                /**
+                 * Vtatlity stat.
+                 */
+                static const unsigned int VIT = 1;
 
-            /**
-             * Spirit stat.
-             */
-            SPR,
+                /**
+                 * Magic stat.
+                 */
+                static const unsigned int MAG = 2;
 
-            /**
-             * Dexterity stat.
-             */
-            DEX,
+                /**
+                 * Spirit stat.
+                 */
+                static const unsigned int SPR = 3;
 
-            /**
-             * Luck stat.
-             */
-            LCK,
+                /**
+                 * Dexterity stat.
+                 */
+                static const unsigned int DEX = 4;
 
-            /**
-             * HP stat.
-             */
-            HP,
+                /**
+                 * Luck stat.
+                 */
+                static const unsigned int LCK = 5;
 
-            /**
-             * MP stat.
-             */
-            MP
+                /**
+                 * HP stat.
+                 */
+                static const unsigned int HP = 6;
+
+                /**
+                 * MP stat.
+                 */
+                static const unsigned int MP = 7;
+        };
+
+        /**
+         * Window corners.
+         */
+        class CORNER{
+
+            public:
+
+                /**
+                 * Top left window corner.
+                 */
+                static const unsigned int T_L = 0;
+
+                /**
+                 * Top right window corner.
+                 */
+                static const unsigned int T_R = 1;
+
+                /**
+                 * Bottom right window corner.
+                 */
+                static const unsigned int B_R = 2;
+
+                /**
+                 * Bottom left window corner.
+                 */
+                static const unsigned int B_L = 3;
+        };
+
+        /**
+         * Colour codes
+         */
+        class COLOUR{
+
+            public:
+
+                /**
+                 * Red colour.
+                 */
+                static const unsigned int R = 0;
+
+                /**
+                 * Green colour.
+                 */
+                static const unsigned int G = 1;
+
+                /**
+                 * Blue colour.
+                 */
+                static const unsigned int B = 2;
         };
 
     private:

+ 527 - 20
V-Gears/include/core/SavemapManager.h

@@ -358,29 +358,538 @@ class SavemapManager : public Ogre::Singleton<SavemapManager>{
          * @return True if the slot is empty, or false if a game is saved there. If an invalid slot
          * is queried, it will always return true.
          */
-        bool SlotIsEmpty(const unsigned int slot);
+        bool IsSlotEmpty(const unsigned int slot);
 
         /**
-         * Generates a string with all the required data to generate a preview of a savemap.
+         * Retrieves the control key from a saved savemap.
          *
-         * The included information contains the following fields, separated by the character "#":
-         * - Slot
-         * - Control key
-         * - Party money
-         * - Game time (in seconds)
-         * - Location text
-         * - Party member 1 name
-         * - Party member 1 level
-         * - Party member 1 character ID.
-         * - Party member 2 character ID.
-         * - Party member 3 character ID.
+         * @param[in] slot The slot to read from.
+         * @return The control key of the slot. If an invalid slot is specified, or if the slot is
+         * empty, an empty string.
+         */
+        std::string GetSlotControlKey(const unsigned int slot);
+
+        /**
+         * Retrieves a colour component from a window corner from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] corner The window corner. See {@see Savemap::Corner}.
+         * @param[in] corner The color component to get. See {@see Savemap::Colour}.
+         * @return The color component of the specified corner of windows. If an invalid slot is
+         * specified, or if the slot is empty, or if an invalid corner or color are requested, 0.
+         */
+        unsigned int GetSlotWindowCornerColourComponent(
+          const unsigned int slot, const unsigned int corner, const unsigned int comp
+        );
+
+        /**
+         * Retrieves the money from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @return The money of the slot. If an invalid slot is specified, or if the slot is
+         * empty, 0.
+         */
+        unsigned int GetSlotMoney(const unsigned int slot);
+
+        /**
+         * Retrieves the total playtime from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @return The total playtime, in seconds. If an invalid slot is specified, or if the slot
+         * is empty, 0.
+         */
+        unsigned int GetSlotGameTime(const unsigned int slot);
+
+        /**
+         * Retrieves the time in the timer from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @return The timer time, in seconds. If an invalid slot is specified, or if the slot
+         * is empty, or if there is no timer saved, 0.
+         */
+        unsigned int GetSlotCountdownTime(const unsigned int slot);
+
+        /**
+         * Retrieves the ID of a party member from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] pos Position in the party.
+         * @return The ID of the character at the requested position. If an invalid slot is
+         * specified, or if the slot is empty, or if an invalid position is passed, or if there is
+         * no character at the requested position, -1.
+         */
+        int GetSlotPartyMember(const unsigned int slot, const unsigned int pos);
+
+        /**
+         * Retrieves the ID of an item in the inventory from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] pos Position in the inventory.
+         * @return The ID of the item at the requested inventory position. If an invalid slot is
+         * specified, or if the slot is empty, or if an invalid position is passed, or if there is
+         * no item at the requested position, 0.
+         */
+        unsigned int GetSlotItemAtPosId(const unsigned int slot, const unsigned int pos);
+
+        /**
+         * Retrieves the quantity of an item in the inventory from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] pos Position in the inventory.
+         * @return The quantity of the item at the requested inventory position. If an invalid slot
+         * is specified, or if the slot is empty, or if an invalid position is passed, or if there
+         * is no item at the requested position, 0.
+         */
+        unsigned int GetSlotItemAtPosQty(const unsigned int slot, const unsigned int pos);
+
+        /**
+         * Checks the status of a key item from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] id Key item ID.
+         * @return True if the key item is owned, false if not. If an invalid slot is specified,
+         * or if the slot is empty, or if an invalid id is passed, false.
+         */
+        bool GetSlotKeyItem(const unsigned int slot, const unsigned int id);
+
+        /**
+         * Retrieves the ID of a materia in the inventory from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] pos Position in the materia inventory.
+         * @return The ID of the materia at the requested inventory position. If an invalid slot is
+         * specified, or if the slot is empty, or if an invalid position is passed, or if there is
+         * no materia at the requested position, -1.
+         */
+        int GetSlotMateriaAtPosId(const unsigned int slot, const unsigned int pos);
+
+        /**
+         * Retrieves the AP of a materia in the inventory from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] pos Position in the materia inventory.
+         * @return The AP of the materia at the requested inventory position. If an invalid slot
+         * is specified, or if the slot is empty, or if an invalid position is passed, or if there
+         * is no materia at the requested position, 0.
+         */
+        unsigned int GetSlotMateriaAtPosAp(const unsigned int slot, const unsigned int pos);
+
+        /**
+         * Checks if there is an Enemy Skill materia at a inventory position from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] pos Position in the materia inventory.
+         * @return True if the materia in the specified position is an Enemy Skill materia, false
+         * if not. If an invalid slot is specified, or if the slot is empty, or if an invalid
+         * position is passed, or if there is no materia at that position, false.
+         */
+        bool IsSlotMateriaAtPosESkill(const unsigned int slot, const unsigned int pos);
+
+        /**
+         * Checks if a a enemy skill is learned by a materia at a position from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] pos Position in the materia inventory.
+         * @param[in] skill Skill ID, starting from 0.
+         * @return True if the materia in the specified position exists, is an Enemy Skill materia
+         * and has learned the specified skill. False in any other case.
+         */
+        bool IsSlotMateriaAtPosESkillLearned(
+          const unsigned int slot, const unsigned int pos, const unsigned int skill
+        );
+
+        /**
+         * Retrieves the ID of a materia in the stash from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] pos Position in the materia stash.
+         * @return The ID of the materia at the requested stash position. If an invalid slot is
+         * specified, or if the slot is empty, or if an invalid position is passed, or if there is
+         * no materia at the requested position, -1.
+         */
+        int GetSlotStashAtPosId(const unsigned int slot, const unsigned int pos);
+
+        /**
+         * Retrieves the AP of a materia in the stash from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] pos Position in the materia stash.
+         * @return The AP of the materia at the requested stash position. If an invalid slot
+         * is specified, or if the slot is empty, or if an invalid position is passed, or if there
+         * is no materia at the requested position, 0.
+         */
+        unsigned int GetSlotStashAtPosAp(const unsigned int slot, const unsigned int pos);
+
+        /**
+         * Checks if there is an Enemy Skill materia at a stash position from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] pos Position in the materia stash.
+         * @return True if the materia in the specified position is an Enemy Skill materia, false
+         * if not. If an invalid slot is specified, or if the slot is empty, or if an invalid
+         * position is passed, or if there is no materia at that position, false.
+         */
+        bool IsSlotStashAtPosESkill(const unsigned int slot, const unsigned int pos);
+
+        /**
+         * Checks if a a enemy skill is learned by a mat. at a stash position from a saved savemap.
          *
-         * @param[in]
-         * @return The generated string. An empty string if a wrong slot is specified, or the slot
-         * is empty.
+         * @param[in] slot The slot to read from.
+         * @param[in] pos Position in the materia stash.
+         * @param[in] skill Skill ID, starting from 0.
+         * @return True if the materia in the specified position exists, is an Enemy Skill materia
+         * and has learned the specified skill. False in any other case.
          */
-        //char* GetPreviewData(const unsigned int slot);
-        std::string GetPreviewData(const unsigned int slot);
+        bool IsSlotStashAtPosESkillLearned(
+          const unsigned int slot, const unsigned int pos, const unsigned int skill
+        );
+
+        /**
+         * Retrieves the X coordinate of the player from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @return The X coordinate. If an invalid slot is specified, or if the slot is empty, 0.
+         */
+        unsigned int GetSlotLocationX(const unsigned int slot);
+
+        /**
+         * Retrieves the Y coordinate of the player from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @return The Y coordinate. If an invalid slot is specified, or if the slot is empty, 0.
+         */
+        unsigned int GetSlotLocationY(const unsigned int slot);
+
+        /**
+         * Retrieves the Z coordinate of the player from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @return The Z coordinate. If an invalid slot is specified, or if the slot is empty, or
+         * if the coordinate can be ignored -1.
+         */
+        int GetSlotLocationZ(const unsigned int slot);
+
+        /**
+         * Retrieves the walkmesh triangle of the player from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @return The triangle ID. If an invalid slot is specified, or if the slot is empty, 0.
+         */
+        unsigned int GetSlotLocationTriangle(const unsigned int slot);
+
+        /**
+         * Retrieves the facing angle of the player from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @return The angle. If an invalid slot is specified, or if the slot is empty, 0.
+         */
+        int GetSlotLocationAngle(const unsigned int slot);
+
+        /**
+         * Retrieves the field ID from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @return The field ID. If an invalid slot is specified, or if the slot is empty, or if the
+         * savemap is saved in the worldmap, an empty string.
+         */
+        std::string GetSlotLocationField(const unsigned int slot);
+
+        /**
+         * Retrieves the location name from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @return The location name to be displayed in the save slot. If an invalid slot is
+         * specified, or if the slot is empty, or if the location name has not been saved, an empty
+         * string.
+         */
+        std::string GetSlotLocationName(const unsigned int slot);
+
+        /**
+         * Retrieves a setting from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] key Setting key.
+         * @return The setting value.
+         * @todo Implement and document properly.
+         */
+        int GetSlotSetting(const unsigned int slot, const unsigned int key);
+
+        /**
+         * Retrieves the char ID of a character from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] id The character ID.
+         * @return The char ID of the character. If an invalid slot is specified, or if the slot is
+         * empty, or if an invalid id is passed, or if the character doesn't have a char ID, -1.
+         */
+        int GetSlotCharacterCharId(const unsigned int slot, const unsigned int id);
+
+        /**
+         * Retrieves the name of a character from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] id The character ID.
+         * @return The name of the character. If an invalid slot is specified, or if the slot is
+         * empty, or if an invalid id is passed, an empty string.
+         */
+        std::string GetSlotCharacterName(const unsigned int slot, const unsigned int id);
+
+        /**
+         * Retrieves the level of a character from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] id The character ID.
+         * @return The level of the character. If an invalid slot is specified, or if the slot is
+         * empty, or if an invalid id is passed, 1.
+         */
+        unsigned int GetSlotCharacterLevel(const unsigned int slot, const unsigned int id);
+
+        /**
+         * Retrieves the total kills of a character from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] id The character ID.
+         * @return The kills of the character. If an invalid slot is specified, or if the slot is
+         * empty, or if an invalid id is passed, 0.
+         */
+        unsigned int GetSlotCharacterKills(const unsigned int slot, const unsigned int id);
+
+        /**
+         * Checks the enabled status of a character from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] id The character ID.
+         * @return True if the character is enabled, false if not. If an invalid slot is specified,
+         * or if the slot is empty, or if an invalid id is passed, false.
+         */
+        bool IsSlotCharacterEnabled(const unsigned int slot, const unsigned int id);
+
+        /**
+         * Checks the lock status of a character from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] id The character ID.
+         * @return True if the character is enabled, false if not. If an invalid slot is specified,
+         * or if the slot is empty, or if an invalid id is passed, false.
+         */
+        bool IsSlotCharacterLocked(const unsigned int slot, const unsigned int id);
+
+        /**
+         * Checks the row of a character from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] id The character ID.
+         * @return True if the character is in the back row, false if not. If an invalid slot is
+         * specified, or if the slot is empty, or if an invalid id is passed, false.
+         */
+        bool IsSlotCharacterBackRow(const unsigned int slot, const unsigned int id);
+
+        /**
+         * Retrieves the total experience of a character from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] id The character ID.
+         * @return The experience of the character. If an invalid slot is specified, or if the slot
+         * is empty, or if an invalid id is passed, 0.
+         */
+        unsigned int GetSlotCharacterExp(const unsigned int slot, const unsigned int id);
+
+        /**
+         * Retrieves the experience for next level of a character from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] id The character ID.
+         * @return The experience of the character. If an invalid slot is specified, or if the slot
+         * is empty, or if an invalid id is passed, 0.
+         */
+        unsigned int GetSlotCharacterExpToNext(const unsigned int slot, const unsigned int id);
+
+        /**
+         * Retrieves the current limit level of a character from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] id The character ID.
+         * @return The limit level of the character. If an invalid slot is specified, or if the
+         * slot is empty, or if an invalid id is passed, 0.
+         */
+        unsigned int GetSlotCharacterLimitLevel(const unsigned int slot, const unsigned int id);
+
+        /**
+         * Retrieves the current limit bar status level of a character from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] id The character ID.
+         * @return The limit bar status of the character. If an invalid slot is specified, or if
+         * the slot is empty, or if an invalid id is passed, 0.
+         */
+        unsigned int GetSlotCharacterLimitBar(const unsigned int slot, const unsigned int id);
+
+        /**
+         * Retrieves the ID of the weapon of a character from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] id The character ID.
+         * @return The character's weapon ID. If an invalid slot is specified, or if the slot is
+         * empty, or if an invalid id is passed, 0.
+         */
+        unsigned int GetSlotCharacterWeaponId(const unsigned int slot, const unsigned int id);
+
+        /**
+         * Retrieves the ID of the armor of a character from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] id The character ID.
+         * @return The character's armor ID. If an invalid slot is specified, or if the slot is
+         * empty, or if an invalid id is passed, 0.
+         */
+        unsigned int GetSlotCharacterArmorId(const unsigned int slot, const unsigned int id);
+
+        /**
+         * Retrieves the ID of the accessory of a character from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] id The character ID.
+         * @return The character's accessory ID. If an invalid slot is specified, or if the slot is
+         * empty, or if an invalid id is passed, or if the character has no accessory equipped, -1.
+         */
+        int GetSlotCharacterAccessoryId(const unsigned int slot, const unsigned int id);
+
+        /**
+         * Retrieves the base value of a stat of a character from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] id The character ID.
+         * @param[in] stat The stat ID (see {@see Savemap::STAT}).
+         * @return The base value of the specified stat. If an invalid slot is specified, or if the
+         * slot is empty, or if an invalid id or stat is passed, 0.
+         */
+        unsigned int GetSlotCharacterStatBase(
+          const unsigned int slot, const unsigned int id, const unsigned int stat
+        );
+
+        /**
+         * Retrieves the extra value of a stat of a character from a saved savemap.
+         *
+         * For HP and MP, the extra value means the current value. For any other stat, the bonus
+         * gained by using sources.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] id The character ID.
+         * @param[in] stat The stat ID (see {@see Savemap::STAT}).
+         * @return The extra value of the specified stat. If an invalid slot is specified, or if
+         * the slot is empty, or if an invalid id or stat is passed, 0.
+         */
+        unsigned int GetSlotCharacterStatExtra(
+          const unsigned int slot, const unsigned int id, const unsigned int stat
+        );
+
+        /**
+         * Retrieves the uses of a character's limit level from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] id The character ID.
+         * @param[in] level The limit level.
+         * @return Number of uses of the techniques in the specified limit level. If an invalid
+         * slot is specified, or if the slot is empty, or if an invalid id or limit level is
+         * passed, 0.
+         */
+        unsigned int GetSlotCharacterLimitUses(
+          const unsigned int slot, const unsigned int id, const unsigned int level
+        );
+
+        /**
+         * Checks if a limit technique is learned by a character from a savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] id The character ID.
+         * @param[in] level The limit level.
+         * @param[in] tech The technique position in the level.
+         * @return True if the technique has been learned, false if not. If an invalid slot is
+         * specified, or if the slot is empty, or if an invalid id, limit level or technique is
+         * passed, false.
+         */
+        bool IsSlotCharacterLimitLearned(
+          const unsigned int slot, const unsigned int id,
+          const unsigned int level, const unsigned int tech
+        );
+
+        /**
+         * Retrieves the ID of an equipped materia from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] id The character ID.
+         * @param[in] weapon If false, check materia equipped in the weapon. If false, check
+         * materia equiped in the armor.
+         * @param[in] pos Position in the equipment slots.
+         * @return The ID of the equipped materia. If an invalid slot is specified, or if the slot
+         * is empty, or if an invalid id or position is passed, or if there is no materia at the
+         * requested position, -1.
+         */
+        int GetSlotCharacterMateriaId(
+          const unsigned int slot, const unsigned int id, const bool weapon, const unsigned int pos
+        );
+
+        /**
+         * Retrieves the AP of an equipped materia from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] id The character ID.
+         * @param[in] weapon If false, check materia equipped in the weapon. If false, check
+         * materia equiped in the armor.
+         * @param[in] pos Position in the equipment slots.
+         * @return The AP of the equipped materia. If an invalid slot is specified, or if the slot
+         * is empty, or if an invalid id or position is passed, or if there is no materia at the
+         * requested position, 0.
+         */
+        unsigned int GetSlotCharacterMateriaAp(
+          const unsigned int slot, const unsigned int id, const bool weapon, const unsigned int pos
+        );
+
+        /**
+         * Checks if an equipped materia is Enemy Skill from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] id The character ID.
+         * @param[in] weapon If false, check materia equipped in the weapon. If false, check
+         * materia equiped in the armor.
+         * @param[in] pos Position in the equipment slots.
+         * @return True if the materia in the specified position is an Enemy Skill materia, false
+         * if not. If an invalid id or slot is specified, or if the slot is empty, or if an invalid
+         * position is passed, or if there is no materia at that position, false.
+         */
+        bool IsSlotCharacterMateriaESkill(
+          const unsigned int slot, const unsigned int id, const bool weapon, const unsigned int pos
+        );
+
+        /**
+         * Checks if a a enemy skill is learned by a equipped materia from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] id The character ID.
+         * @param[in] weapon If false, check materia equipped in the weapon. If false, check
+         * materia equiped in the armor.
+         * @param[in] pos Position in the equipment slots.
+         * @param[in] skill Skill ID, starting from 0.
+         * @return True if the materia in the specified position exists, is an Enemy Skill materia
+         * and has learned the specified skill. False in any other case.
+         */
+        bool IsSlotCharacterMateriaESkillLearned(
+          const unsigned int slot, const unsigned int id, const bool weapon,
+          const unsigned int pos, const unsigned int skill
+        );
+
+        /**
+         * Retrieves the value of a bank address from a saved savemap.
+         *
+         * @param[in] slot The slot to read from.
+         * @param[in] bank The bank ID.
+         * @param[in] address The address in the bank.
+         * @return The value. If an invalid slot is specified, or if the slot is empty, or if an
+         * invalid bank or address level is passed, 0.
+         */
+        int GetSlotData(
+          const unsigned int slot, const unsigned int bank, const unsigned int address
+        );
 
     private:
 
@@ -409,8 +918,6 @@ class SavemapManager : public Ogre::Singleton<SavemapManager>{
          */
         bool savemaps_read_;
 
-        //char* temp_;
-
 };
 
 

+ 259 - 5
V-Gears/include/core/ScriptManagerBinds.h

@@ -29,6 +29,14 @@
 #include "TextManager.h"
 #include "modules/worldmap/WorldMapModule.h"
 
+
+/*
+ * TODO:
+ *
+ * If I manage to upgrade luabind version (or even better, remove it and use an external one),
+ * I could pass entire objects to Lua scripts as tables, and this will be waaaaay easier.
+ */
+
 /**
  * Prints to the game console.
  *
@@ -279,6 +287,9 @@ void ScriptManager::InitBinds(){
     // Commands for the savemap manager.
     luabind::module(lua_state_)[
         luabind::class_<SavemapManager>("SavemapManager")
+          .def(
+            "release", (void(SavemapManager::*)()) &SavemapManager::Release
+          )
           .def(
             "get_current_savemap",
             (Savemap*(SavemapManager::*)()) &SavemapManager::GetCurrentSavemap
@@ -402,13 +413,256 @@ void ScriptManager::InitBinds(){
             "save", (bool(SavemapManager::*)(const unsigned int, const bool)) &SavemapManager::Save
           )
           .def(
-            "slot_is_empty",
-            (bool(SavemapManager::*)(const unsigned int)) &SavemapManager::SlotIsEmpty
+            "is_slot_empty",
+            (bool(SavemapManager::*)(const unsigned int)) &SavemapManager::IsSlotEmpty
           )
           .def(
-            "get_preview_data",
-             (std::string(SavemapManager::*)(const unsigned int)) &SavemapManager::GetPreviewData
-           )
+            "get_slot_control_key",
+            (std::string(SavemapManager::*)(const unsigned int)) &SavemapManager::GetSlotControlKey
+          )
+          .def(
+            "get_slot_control_key",
+            (unsigned int(SavemapManager::*)(
+              const unsigned int, const unsigned int, const unsigned int
+            )) &SavemapManager::GetSlotWindowCornerColourComponent
+          )
+          .def(
+            "get_slot_money",
+            (unsigned int(SavemapManager::*)(const unsigned int)) &SavemapManager::GetSlotMoney
+          )
+          .def(
+            "get_slot_game_time",
+            (unsigned int(SavemapManager::*)(const unsigned int)) &SavemapManager::GetSlotGameTime
+          )
+          .def(
+            "get_slot_countdown_time",
+            (unsigned int(SavemapManager::*)(const unsigned int))
+              &SavemapManager::GetSlotCountdownTime
+          )
+          .def(
+            "get_slot_party_member",
+            (int(SavemapManager::*)(const unsigned int, const unsigned int))
+              &SavemapManager::GetSlotPartyMember
+          )
+          .def(
+            "get_slot_item_at_pos_id",
+            (unsigned int(SavemapManager::*)(const unsigned int, const unsigned int))
+              &SavemapManager::GetSlotItemAtPosId
+          )
+          .def(
+            "get_slot_item_at_pos_qty",
+            (unsigned int(SavemapManager::*)(const unsigned int, const unsigned int))
+              &SavemapManager::GetSlotItemAtPosQty
+          )
+          .def(
+            "get_slot_key_item",
+            (bool(SavemapManager::*)(const unsigned int, const unsigned int))
+              &SavemapManager::GetSlotKeyItem
+          )
+          .def(
+            "get_slot_materia_at_pos_id",
+            (int(SavemapManager::*)(const unsigned int, const unsigned int))
+              &SavemapManager::GetSlotMateriaAtPosId
+          )
+          .def(
+            "get_slot_materia_at_pos_ap",
+            (unsigned int(SavemapManager::*)(const unsigned int, const unsigned int))
+              &SavemapManager::GetSlotMateriaAtPosAp
+          )
+          .def(
+            "is_slot_materia_at_pos_e_skill",
+            (bool(SavemapManager::*)(const unsigned int, const unsigned int))
+              &SavemapManager::IsSlotMateriaAtPosESkill
+          )
+          .def(
+            "is_slot_materia_at_pos_e_skill_learned",
+            (bool(SavemapManager::*)(
+              const unsigned int, const unsigned int, const unsigned int
+            )) &SavemapManager::IsSlotMateriaAtPosESkillLearned
+          )
+          .def(
+            "get_slot_stash_at_pos_id",
+            (int(SavemapManager::*)(const unsigned int, const unsigned int))
+              &SavemapManager::GetSlotStashAtPosId
+          )
+          .def(
+            "get_slot_stash_at_pos_ap",
+            (unsigned int(SavemapManager::*)(const unsigned int, const unsigned int))
+              &SavemapManager::GetSlotStashAtPosAp
+          )
+          .def(
+            "is_slot_stash_at_pos_e_skill",
+            (bool(SavemapManager::*)(const unsigned int, const unsigned int))
+              &SavemapManager::IsSlotStashAtPosESkill
+          )
+          .def(
+            "is_slot_stash_at_pos_e_skill_learned",
+            (bool(SavemapManager::*)(
+              const unsigned int, const unsigned int, const unsigned int
+            )) &SavemapManager::IsSlotStashAtPosESkillLearned
+          )
+          .def(
+            "get_slot_location_x",
+            (unsigned int(SavemapManager::*)(const unsigned int)) &SavemapManager::GetSlotLocationX
+          )
+          .def(
+            "get_slot_location_y",
+            (unsigned int(SavemapManager::*)(const unsigned int)) &SavemapManager::GetSlotLocationX
+          )
+          .def(
+            "get_slot_location_z",
+            (int(SavemapManager::*)(const unsigned int)) &SavemapManager::GetSlotLocationZ
+          )
+          .def(
+            "get_slot_location_triangle",
+            (unsigned int(SavemapManager::*)(const unsigned int))
+              &SavemapManager::GetSlotLocationTriangle
+          )
+          .def(
+            "get_slot_location_angle",
+            (unsigned int(SavemapManager::*)(const unsigned int))
+              &SavemapManager::GetSlotLocationAngle
+          )
+          .def(
+            "get_slot_location_field",
+            (std::string(SavemapManager::*)(const unsigned int))
+              &SavemapManager::GetSlotLocationField
+          )
+          .def(
+            "get_slot_location_name",
+            (std::string(SavemapManager::*)(const unsigned int))
+              &SavemapManager::GetSlotLocationName
+          )
+          .def(
+            "get_slot_setting",
+            (int(SavemapManager::*)(const unsigned int, const unsigned int))
+              &SavemapManager::GetSlotSetting
+          )
+          .def(
+            "get_slot_character_char_id",
+            (int(SavemapManager::*)(const unsigned int, const unsigned int))
+              &SavemapManager::GetSlotCharacterCharId
+          )
+          .def(
+            "get_slot_character_name",
+            (std::string(SavemapManager::*)(const unsigned int, const unsigned int))
+              &SavemapManager::GetSlotCharacterName
+          )
+          .def(
+            "get_slot_character_level",
+            (unsigned int(SavemapManager::*)(const unsigned int, const unsigned int))
+              &SavemapManager::GetSlotCharacterLevel
+          )
+          .def(
+            "get_slot_character_kills",
+            (unsigned int(SavemapManager::*)(const unsigned int, const unsigned int))
+              &SavemapManager::GetSlotCharacterKills
+          )
+          .def(
+            "is_slot_character_enabled",
+            (bool(SavemapManager::*)(const unsigned int, const unsigned int))
+              &SavemapManager::IsSlotCharacterEnabled
+          )
+          .def(
+            "is_slot_character_locked",
+            (bool(SavemapManager::*)(const unsigned int, const unsigned int))
+              &SavemapManager::IsSlotCharacterLocked
+          )
+          .def(
+            "is_slot_character_back_row",
+            (bool(SavemapManager::*)(const unsigned int, const unsigned int))
+              &SavemapManager::IsSlotCharacterBackRow
+          )
+          .def(
+            "get_slot_character_exp",
+            (unsigned int(SavemapManager::*)(const unsigned int, const unsigned int))
+              &SavemapManager::GetSlotCharacterExp
+          )
+          .def(
+            "get_slot_character_exp_to_next",
+            (unsigned int(SavemapManager::*)(const unsigned int, const unsigned int))
+              &SavemapManager::GetSlotCharacterExpToNext
+          )
+          .def(
+            "get_slot_character_limit_level",
+            (unsigned int(SavemapManager::*)(const unsigned int, const unsigned int))
+              &SavemapManager::GetSlotCharacterLimitLevel
+          )
+          .def(
+            "get_slot_character_limit_bar",
+            (unsigned int(SavemapManager::*)(const unsigned int, const unsigned int))
+              &SavemapManager::GetSlotCharacterLimitBar
+          )
+          .def(
+            "get_slot_character_weapon_id",
+            (unsigned int(SavemapManager::*)(const unsigned int, const unsigned int))
+              &SavemapManager::GetSlotCharacterWeaponId
+          )
+          .def(
+            "get_slot_character_armor_id",
+            (unsigned int(SavemapManager::*)(const unsigned int, const unsigned int))
+              &SavemapManager::GetSlotCharacterArmorId
+          )
+          .def(
+            "get_slot_character_accessory_id",
+            (int(SavemapManager::*)(const unsigned int, const unsigned int))
+              &SavemapManager::GetSlotCharacterAccessoryId
+          )
+          .def(
+            "get_slot_character_stat_base",
+            (unsigned int(SavemapManager::*)(
+              const unsigned int, const unsigned int, const unsigned int
+            )) &SavemapManager::GetSlotCharacterStatBase
+          )
+          .def(
+            "get_slot_character_stat_extra",
+            (unsigned int(SavemapManager::*)(
+              const unsigned int, const unsigned int, const unsigned int
+            )) &SavemapManager::GetSlotCharacterStatExtra
+          )
+          .def(
+            "get_slot_character_limit_uses",
+            (unsigned int(SavemapManager::*)(
+              const unsigned int, const unsigned int, const unsigned int
+            )) &SavemapManager::GetSlotCharacterLimitUses
+          )
+          .def(
+            "is_slot_character_limit_learned",
+            (unsigned int(SavemapManager::*)(
+              const unsigned int, const unsigned int, const unsigned int, const unsigned int
+            )) &SavemapManager::IsSlotCharacterLimitLearned
+          )
+          .def(
+            "get_slot_character_materia_id",
+            (int(SavemapManager::*)(
+              const unsigned int, const unsigned int, const bool, const unsigned int
+            )) &SavemapManager::GetSlotCharacterMateriaId
+          )
+          .def(
+            "get_slot_character_materia_ap",
+            (unsigned int(SavemapManager::*)(
+              const unsigned int, const unsigned int, const bool, const unsigned int
+            )) &SavemapManager::GetSlotCharacterMateriaAp
+          )
+          .def(
+            "get_slot_character_materia_e_skill",
+            (bool(SavemapManager::*)(
+              const unsigned int, const unsigned int, const bool,
+              const unsigned int, const unsigned int
+            )) &SavemapManager::IsSlotCharacterMateriaESkill
+          )
+          .def(
+            "get_slot_character_materia_e_skill_learned",
+            (bool(SavemapManager::*)(
+              const unsigned int, const unsigned int, const bool,
+              const unsigned int, const unsigned int
+            )) &SavemapManager::IsSlotCharacterMateriaESkillLearned
+          )
+          .def(
+            "get_slot_data",
+            (int(SavemapManager::*)(const unsigned int, const unsigned int, const unsigned int))
+              &SavemapManager::GetSlotData
+          )
     ];
 
     // 2D background and camera commands

+ 288 - 9
V-Gears/src/core/Savemap.cpp

@@ -23,7 +23,7 @@
 #include "common/TypeDefine.h"
 
 Savemap::Savemap():
-  empty_(true), control_("X"), money_(0), seconds_(0), countdown_(0), slot_(-1)
+  empty_(true), control_(""), money_(0), seconds_(0), countdown_(0), slot_(-1)
 {
     for (int i = 0; i < 4; i ++){
         window_colours_[i][0] = 0;
@@ -62,7 +62,7 @@ Savemap::Savemap():
     }
     for (int i = 0; i < MAX_CHARACTERS; i ++){
         characters_[i].id = i;
-        characters_[i].char_id = 0;
+        characters_[i].char_id = -1;
         characters_[i].enabled = false;
         characters_[i].locked = false;
         characters_[i].name = "";
@@ -385,13 +385,292 @@ void Savemap::SetCharacterStatus(
 
 bool Savemap::IsEmpty(){return empty_;}
 
-std::string Savemap::GetPreviewData(){
-    std::string data = "";
-    data += std::to_string(slot_) + "#" + control_ + "#" + std::to_string(money_) + "#"
-      + std::to_string(seconds_) + "#" + location_.name + "#" + characters_[party_[0]].name + "#" +
-      std::to_string(characters_[party_[0]].level) + "#" + std::to_string(party_[0]) + "#"
-      + std::to_string(party_[1]) + "#" + std::to_string(party_[2]);
-    return data;
+std::string Savemap::GetControlKey(){return control_;}
+
+unsigned int Savemap::GetWindowCornerColourComponent(
+  const unsigned int corner, const unsigned int comp
+){
+    if (corner < 4 && comp < 3) return window_colours_[corner][comp];
+    else return 0;
+}
+
+unsigned int Savemap::GetMoney(){return money_;}
+
+unsigned int Savemap::GetGameTime(){return seconds_;}
+
+unsigned int Savemap::GetCountdownTime(){return countdown_;}
+
+int Savemap::GetPartyMember(const unsigned int pos){
+    if (pos < MAX_PARTY_MEMBERS) return party_[pos];
+    else return -1;
+}
+
+unsigned int Savemap::GetItemAtPosId(const unsigned int pos){
+    if (pos >= MAX_ITEM_SLOTS) return 0;
+    else if (items_[pos].quantity == 0) return 0;
+    else return items_[pos].id;
+}
+
+unsigned int Savemap::GetItemAtPosQty(const unsigned int pos){
+    if (pos >= MAX_ITEM_SLOTS) return 0;
+    else return items_[pos].quantity;
+}
+
+bool Savemap::GetKeyItem(const unsigned int id){
+    if (id >= MAX_KEY_ITEM_SLOTS) return false;
+    else return key_items_[id];
+}
+
+int Savemap::GetMateriaAtPosId(const unsigned int pos){
+    if (pos >= MAX_MATERIA_SLOTS) return -1;
+    else return materia_[pos].id;
+}
+
+unsigned int Savemap::GetMateriaAtPosAp(const unsigned int pos){
+    if (pos >= MAX_MATERIA_SLOTS) return 0;
+    else if (materia_[pos].id < 0) return 0;
+    else if (materia_[pos].enemy_skill) return 0;
+    else return materia_[pos].ap;
+}
+
+bool Savemap::IsMateriaAtPosESkill(const unsigned int pos){
+    if (pos >= MAX_MATERIA_SLOTS) return false;
+    else if (materia_[pos].id < 0) return false;
+    else return materia_[pos].enemy_skill;
+}
+
+bool Savemap::IsMateriaAtPosESkillLearned(const unsigned int pos, const unsigned int skill){
+    if (pos >= MAX_MATERIA_SLOTS) return false;
+    else if (materia_[pos].id < 0) return false;
+    else if (materia_[pos].enemy_skill == false) return false;
+    else if (skill >= MAX_ENEMY_SKILLS) return false;
+    else return materia_[pos].enemy_skill_learned[skill];
+}
+
+int Savemap::GetStashAtPosId(const unsigned int pos){
+    if (pos >= MAX_STASH_SLOTS) return -1;
+    else return materia_stash_[pos].id;
+}
+
+unsigned int Savemap::GetStashAtPosAp(const unsigned int pos){
+    if (pos >= MAX_STASH_SLOTS) return 0;
+    else if (materia_stash_[pos].id < 0) return 0;
+    else if (materia_stash_[pos].enemy_skill) return 0;
+    else return materia_stash_[pos].ap;
+}
+
+bool Savemap::IsStashAtPosESkill(const unsigned int pos){
+    if (pos >= MAX_STASH_SLOTS) return false;
+    else if (materia_stash_[pos].id < 0) return false;
+    else return materia_stash_[pos].enemy_skill;
+}
+
+bool Savemap::IsStashAtPosESkillLearned(const unsigned int pos, const unsigned int skill){
+    if (pos >= MAX_STASH_SLOTS) return false;
+    else if (materia_stash_[pos].id < 0) return false;
+    else if (materia_stash_[pos].enemy_skill == false) return false;
+    else if (skill >= MAX_ENEMY_SKILLS) return false;
+    else return materia_stash_[pos].enemy_skill_learned[skill];
+}
+
+unsigned int Savemap::GetLocationX(){return location_.x;}
+
+unsigned int Savemap::GetLocationY(){return location_.y;}
+
+int Savemap::GetLocationZ(){return location_.z;}
+
+unsigned int Savemap::GetLocationTriangle(){return location_.triangle;}
+
+int Savemap::GetLocationAngle(){return location_.angle;}
+
+std::string Savemap::GetLocationField(){return location_.field;}
+
+std::string Savemap::GetLocationName(){return location_.name;}
+
+int Savemap::GetSetting(const unsigned int key){
+    // TODO: Implement.
+    return 0;
+}
+
+int Savemap::GetCharacterCharId(const unsigned int id){
+    if (id >= MAX_CHARACTERS) return -1;
+    else return characters_[id].char_id;
+}
+
+std::string Savemap::GetCharacterName(const unsigned int id){
+    if (id >= MAX_CHARACTERS) return std::string("");
+    else return characters_[id].name;
+}
+
+unsigned int Savemap::GetCharacterLevel(const unsigned int id){
+    if (id >= MAX_CHARACTERS) return 1;
+    else return characters_[id].level;
+}
+
+unsigned int Savemap::GetCharacterKills(const unsigned int id){
+    if (id >= MAX_CHARACTERS) return 0;
+    else return characters_[id].kills;
+}
+
+bool Savemap::IsCharacterEnabled(const unsigned int id){
+    if (id >= MAX_CHARACTERS) return false;
+    else return characters_[id].enabled;
+}
+
+bool Savemap::IsCharacterLocked(const unsigned int id){
+    if (id >= MAX_CHARACTERS) return false;
+    else return characters_[id].locked;
+}
+
+bool Savemap::IsCharacterBackRow(const unsigned int id){
+    if (id >= MAX_CHARACTERS) return false;
+    else return characters_[id].back_row;
+}
+
+unsigned int Savemap::GetCharacterExp(const unsigned int id){
+    if (id >= MAX_CHARACTERS) return 0;
+    else return characters_[id].exp;
+}
+
+unsigned int Savemap::GetCharacterExpToNext(const unsigned int id){
+    if (id >= MAX_CHARACTERS) return 0;
+    else return characters_[id].exp_to_next;
+}
+
+unsigned int Savemap::GetCharacterLimitLevel(const unsigned int id){
+    if (id >= MAX_CHARACTERS) return 0;
+    else return characters_[id].limit_level;
+}
+
+unsigned int Savemap::GetCharacterLimitBar(const unsigned int id){
+    if (id >= MAX_CHARACTERS) return 0;
+    else return characters_[id].limit_bar;
+}
+
+unsigned int Savemap::GetCharacterWeaponId(const unsigned int id){
+    if (id >= MAX_CHARACTERS) return 0;
+    else return characters_[id].weapon.id;
+}
+
+unsigned int Savemap::GetCharacterArmorId(const unsigned int id){
+    if (id >= MAX_CHARACTERS) return 0;
+    else return characters_[id].armor.id;
+}
+
+int Savemap::GetCharacterAccessoryId(const unsigned int id){
+    if (id >= MAX_CHARACTERS) return -1;
+    else return characters_[id].accessory;
+}
+
+unsigned int Savemap::GetCharacterStatBase(const unsigned int id, const unsigned int stat){
+    if (id >= MAX_CHARACTERS) return 0;
+    switch (stat){
+        case STAT::STR: return characters_[id].str.base; break;
+        case STAT::VIT: return characters_[id].vit.base; break;
+        case STAT::MAG: return characters_[id].mag.base; break;
+        case STAT::SPR: return characters_[id].spr.base; break;
+        case STAT::DEX: return characters_[id].dex.base; break;
+        case STAT::LCK: return characters_[id].lck.base; break;
+        case STAT::HP: return characters_[id].hp.base; break;
+        case STAT::MP: return characters_[id].mp.base; break;
+        default: return 0;
+    }
+}
+
+unsigned int Savemap::GetCharacterStatExtra(const unsigned int id, const unsigned int stat){
+    if (id >= MAX_CHARACTERS) return 0;
+    switch (stat){
+        case STAT::STR: return characters_[id].str.extra; break;
+        case STAT::VIT: return characters_[id].vit.extra; break;
+        case STAT::MAG: return characters_[id].mag.extra; break;
+        case STAT::SPR: return characters_[id].spr.extra; break;
+        case STAT::DEX: return characters_[id].dex.extra; break;
+        case STAT::LCK: return characters_[id].lck.extra; break;
+        case STAT::HP: return characters_[id].hp.extra; break;
+        case STAT::MP: return characters_[id].mp.extra; break;
+        default: return 0;
+    }
+}
+
+unsigned int Savemap::GetCharacterLimitUses(const unsigned int id, const unsigned int level){
+    if (id >= MAX_CHARACTERS) return 0;
+    else if (level >= MAX_LIMIT_LEVELS) return 0;
+    else return characters_[id].limit_uses[level];
+}
+
+bool Savemap::IsCharacterLimitLearned(
+  const unsigned int id, const unsigned int level, const unsigned int tech
+){
+    if (id >= MAX_CHARACTERS) return false;
+    else if (level >= MAX_LIMIT_LEVELS) return false;
+    else if (tech >= MAX_LIMIT_TECHNIQUES) return false;
+    else return characters_[id].limits_learned[level][tech];
+}
+
+
+int Savemap::GetCharacterMateriaId(
+  const unsigned int id, const bool weapon, const unsigned int pos
+){
+    if (id >= MAX_CHARACTERS) return -1;
+    else if (pos >= MAX_EQUIP_SLOTS) return -1;
+    if (weapon) return characters_[id].weapon.materia[pos].id;
+    else return characters_[id].armor.materia[pos].id;
+}
+
+unsigned int Savemap::GetCharacterMateriaAp(
+  const unsigned int id, const bool weapon, const unsigned int pos
+){
+    if (id >= MAX_CHARACTERS) return 0;
+    else if (pos >= MAX_EQUIP_SLOTS) return 0;
+    if (weapon){
+        if (characters_[id].weapon.materia[pos].id == -1) return 0;
+        else if (characters_[id].weapon.materia[pos].enemy_skill) return 0;
+        else return characters_[id].weapon.materia[pos].ap;
+    }
+    else{
+        if (characters_[id].armor.materia[pos].id == -1) return 0;
+        else if (characters_[id].armor.materia[pos].enemy_skill) return 0;
+        else return characters_[id].armor.materia[pos].ap;
+    }
+}
+
+bool Savemap::IsCharacterMateriaESkill(
+  const unsigned int id, const bool weapon, const unsigned int pos
+){
+    if (id >= MAX_CHARACTERS) return false;
+    else if (pos >= MAX_EQUIP_SLOTS) return false;
+    if (weapon){
+        if (characters_[id].weapon.materia[pos].id == -1) return false;
+        else return characters_[id].weapon.materia[pos].enemy_skill;
+    }
+    else{
+        if (characters_[id].armor.materia[pos].id == -1) return false;
+        else return characters_[id].armor.materia[pos].enemy_skill;
+    }
+}
+
+bool Savemap::IsCharacterMateriaESkillLearned(
+  const unsigned int id, const bool weapon, const unsigned int pos, const unsigned int skill
+){
+    if (id >= MAX_CHARACTERS) return false;
+    else if (pos >= MAX_EQUIP_SLOTS) return false;
+    else if (skill >= MAX_ENEMY_SKILLS) return false;
+    if (weapon){
+        if (characters_[id].weapon.materia[pos].id == -1) return false;
+        else if (characters_[id].weapon.materia[pos].enemy_skill == false) return false;
+        else return characters_[id].weapon.materia[pos].enemy_skill_learned[skill];
+    }
+    else{
+        if (characters_[id].armor.materia[pos].id == -1) return false;
+        else if (characters_[id].armor.materia[pos].enemy_skill == false) return false;
+        else return characters_[id].armor.materia[pos].enemy_skill_learned[skill];
+    }
+}
+
+int Savemap::GetData(const unsigned int bank, const unsigned int address){
+    if (bank >= BANK_COUNT) return 0;
+    else if (address >= BANK_ADDRESS_COUNT) return 0;
+    else return data_[bank][address];
 }
 
 void Savemap::Write(int slot, std::string file_name){

+ 320 - 47
V-Gears/src/core/SavemapManager.cpp

@@ -48,12 +48,12 @@ std::vector<Savemap*> SavemapManager::GetSavemaps(){
     return saved_savemaps_;
 }
 
-bool SavemapManager::Save(unsigned int slot, bool force){
+bool SavemapManager::Save(unsigned int slot, const bool force){
     if (current_savemap_ == nullptr) return false;
     if (slot >= MAX_SAVE_SLOTS) return false;
     if (!savemaps_read_) ReadSavemaps();
     if (
-      !force && !saved_savemaps_[slot]->IsEmpty()
+        force == false && saved_savemaps_[slot]->IsEmpty() == false
       && current_savemap_->GetControlKey() != saved_savemaps_[slot]->GetControlKey()
     ){
         return false;
@@ -69,7 +69,7 @@ bool SavemapManager::Save(Savemap savemap, unsigned int slot, bool force){
     if (slot >= MAX_SAVE_SLOTS) return false;
     if (!savemaps_read_) ReadSavemaps();
     if (
-      !force && !saved_savemaps_[slot]->IsEmpty()
+      force == false && saved_savemaps_[slot]->IsEmpty() == false
       && savemap.GetControlKey() != saved_savemaps_[slot]->GetControlKey()
     ){
         return false;
@@ -241,56 +241,329 @@ void SavemapManager::SetCharacterStatus(
     current_savemap_->SetCharacterStatus(id, status, inflicted);
 }
 
-bool SavemapManager::SlotIsEmpty(const unsigned int slot){
+bool SavemapManager::IsSlotEmpty(const unsigned int slot){
     if (slot >= MAX_SAVE_SLOTS) return true;
     if (savemaps_read_ == false) ReadSavemaps();
     return saved_savemaps_[slot]->IsEmpty();
 }
 
-/*char* SavemapManager::GetPreviewData(const unsigned int slot){
-    std::cout << "[PREV_DATA] Start\n";
-    std::string data = "X";
-    std::cout << "[PREV_DATA] 1\n";
-    //char *empty_cstr= new char[1];
-    //strcpy(empty_cstr, data.c_str());
-    if (slot >= MAX_SAVE_SLOTS){
-        strcpy(temp_, data.c_str());
-        std::cout << "[PREV_DATA] RET 1 " << temp_ << " \n";
-        return temp_;
-    }
-    std::cout << "[PREV_DATA] 2\n";
+std::string SavemapManager::GetSlotControlKey(const unsigned int slot){
+    if (slot >= MAX_SAVE_SLOTS) return std::string("");
     if (savemaps_read_ == false) ReadSavemaps();
-    std::cout << "[PREV_DATA] 3\n";
-    if (saved_savemaps_[slot]->IsEmpty()){
-        strcpy(temp_, data.c_str());
-        std::cout << "[PREV_DATA] RET 2 " << temp_ << " \n";
-        return temp_;
-    }
-    std::cout << "[PREV_DATA] 4\n";
-    data = saved_savemaps_[slot]->GetPreviewData();
-    std::cout << "[PREV_DATA] 5\n";
-
-    //char cstr[data.length() + 1];
-    //strcpy(cstr, data.c_str());
-    //cstr[data.length()] = '\0';
-    temp_ = (char*) malloc(data.size() + 1);
-    for (int c = 0; c < data.size(); c ++){
-        temp_[c] = data[c];
-        std::cout << "    " << data[c] << " -> " << temp_[c] << "\n";
-    }
-    temp_[data.size()] = '\0';
-    strcpy(temp_, data.c_str());
-    std::cout << "[PREV_DATA] : " << data << " == " << std::string(temp_) << "\n";
-    return temp_;
-}*/
-
-std::string SavemapManager::GetPreviewData(const unsigned int slot){
-    std::string data = "";
-    if (slot >= MAX_SAVE_SLOTS) return data;
-    if (savemaps_read_ == false) ReadSavemaps();
-    if (saved_savemaps_[slot]->IsEmpty()) return data;
-    data = saved_savemaps_[slot]->GetPreviewData();
-    return data;
+    return saved_savemaps_[slot]->GetControlKey();
+}
+
+unsigned int SavemapManager::GetSlotWindowCornerColourComponent(
+  const unsigned int slot, const unsigned int corner, const unsigned int comp
+){
+    if (slot >= MAX_SAVE_SLOTS) return 0;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetWindowCornerColourComponent(corner, comp);
+}
+
+unsigned int SavemapManager::GetSlotMoney(const unsigned int slot){
+    if (slot >= MAX_SAVE_SLOTS) return 0;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetMoney();
+}
+
+unsigned int SavemapManager::GetSlotGameTime(const unsigned int slot){
+    if (slot >= MAX_SAVE_SLOTS) return 0;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetGameTime();
+}
+
+unsigned int SavemapManager::GetSlotCountdownTime(const unsigned int slot){
+    if (slot >= MAX_SAVE_SLOTS) return 0;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetCountdownTime();
+}
+
+int SavemapManager::GetSlotPartyMember(const unsigned int slot, const unsigned int pos){
+    if (slot >= MAX_SAVE_SLOTS) return -1;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetPartyMember(pos);
+}
+
+unsigned int SavemapManager::GetSlotItemAtPosId(const unsigned int slot, const unsigned int pos){
+    if (slot >= MAX_SAVE_SLOTS) return 0;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetItemAtPosId(pos);
+}
+
+unsigned int SavemapManager::GetSlotItemAtPosQty(const unsigned int slot, const unsigned int pos){
+    if (slot >= MAX_SAVE_SLOTS) return 0;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetItemAtPosQty(pos);
+}
+
+bool SavemapManager::GetSlotKeyItem(const unsigned int slot, const unsigned int id){
+    if (slot >= MAX_SAVE_SLOTS) return false;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetKeyItem(id);
+}
+
+int SavemapManager::GetSlotMateriaAtPosId(const unsigned int slot, const unsigned int pos){
+    if (slot >= MAX_SAVE_SLOTS) return -1;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetMateriaAtPosId(pos);
+}
+
+unsigned int SavemapManager::GetSlotMateriaAtPosAp(const unsigned int slot, const unsigned int pos){
+    if (slot >= MAX_SAVE_SLOTS) return 0;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetMateriaAtPosAp(pos);
+}
+
+bool SavemapManager::IsSlotMateriaAtPosESkill(const unsigned int slot, const unsigned int pos){
+    if (slot >= MAX_SAVE_SLOTS) return 0;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->IsMateriaAtPosESkill(pos);
+}
+
+bool SavemapManager::IsSlotMateriaAtPosESkillLearned(const unsigned int slot, const unsigned int pos, const unsigned int skill){
+    if (slot >= MAX_SAVE_SLOTS) return false;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->IsMateriaAtPosESkillLearned(pos, skill);
+}
+
+int SavemapManager::GetSlotStashAtPosId(const unsigned int slot, const unsigned int pos){
+    if (slot >= MAX_SAVE_SLOTS) return -1;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetStashAtPosId(pos);
+}
+
+unsigned int SavemapManager::GetSlotStashAtPosAp(const unsigned int slot, const unsigned int pos){
+    if (slot >= MAX_SAVE_SLOTS) return 0;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetStashAtPosAp(pos);
+}
+
+bool SavemapManager::IsSlotStashAtPosESkill(const unsigned int slot, const unsigned int pos){
+    if (slot >= MAX_SAVE_SLOTS) return false;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->IsStashAtPosESkill(pos);
+}
+
+bool SavemapManager::IsSlotStashAtPosESkillLearned(const unsigned int slot, const unsigned int pos, const unsigned int skill){
+    if (slot >= MAX_SAVE_SLOTS) return false;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->IsStashAtPosESkillLearned(pos, skill);
+}
+
+unsigned int SavemapManager::GetSlotLocationX(const unsigned int slot){
+    if (slot >= MAX_SAVE_SLOTS) return 0;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetLocationX();
+}
+
+unsigned int SavemapManager::GetSlotLocationY(const unsigned int slot){
+    if (slot >= MAX_SAVE_SLOTS) return 0;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetLocationY();
+}
+
+int SavemapManager::GetSlotLocationZ(const unsigned int slot){
+    if (slot >= MAX_SAVE_SLOTS) return -1;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetLocationZ();
+}
+
+unsigned int SavemapManager::GetSlotLocationTriangle(const unsigned int slot){
+    if (slot >= MAX_SAVE_SLOTS) return 0;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetLocationTriangle();
+}
+
+int SavemapManager::GetSlotLocationAngle(const unsigned int slot){
+    if (slot >= MAX_SAVE_SLOTS) return 0;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetLocationAngle();
+}
+
+std::string SavemapManager::GetSlotLocationField(const unsigned int slot){
+    if (slot >= MAX_SAVE_SLOTS) return "";
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetLocationField();
+}
+
+std::string SavemapManager::GetSlotLocationName(const unsigned int slot){
+    if (slot >= MAX_SAVE_SLOTS) return "";
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetLocationName();
+}
+
+int SavemapManager::GetSlotSetting(const unsigned int slot, const unsigned int key){
+    if (slot >= MAX_SAVE_SLOTS) return 0;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetSetting(key);
+}
+
+int SavemapManager::GetSlotCharacterCharId(const unsigned int slot, const unsigned int id){
+    if (slot >= MAX_SAVE_SLOTS) return 0;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetCharacterCharId(id);
+}
+
+std::string SavemapManager::GetSlotCharacterName(const unsigned int slot, const unsigned int id){
+    if (slot >= MAX_SAVE_SLOTS) return "";
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetCharacterName(id);
+}
+
+unsigned int SavemapManager::GetSlotCharacterLevel(const unsigned int slot, const unsigned int id){
+    if (slot >= MAX_SAVE_SLOTS) return 1;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetCharacterLevel(id);
+}
+
+unsigned int SavemapManager::GetSlotCharacterKills(const unsigned int slot, const unsigned int id){
+    if (slot >= MAX_SAVE_SLOTS) return 0;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetCharacterKills(id);
+}
+
+bool SavemapManager::IsSlotCharacterEnabled(const unsigned int slot, const unsigned int id){
+    if (slot >= MAX_SAVE_SLOTS) return false;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->IsCharacterEnabled(id);
+}
+
+bool SavemapManager::IsSlotCharacterLocked(const unsigned int slot, const unsigned int id){
+    if (slot >= MAX_SAVE_SLOTS) return false;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->IsCharacterLocked(id);
+}
+
+bool SavemapManager::IsSlotCharacterBackRow(const unsigned int slot, const unsigned int id){
+    if (slot >= MAX_SAVE_SLOTS) return false;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->IsCharacterBackRow(id);
+}
+
+unsigned int SavemapManager::GetSlotCharacterExp(const unsigned int slot, const unsigned int id){
+    if (slot >= MAX_SAVE_SLOTS) return 0;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetCharacterExp(id);
+}
+
+unsigned int SavemapManager::GetSlotCharacterExpToNext(
+  const unsigned int slot, const unsigned int id
+){
+    if (slot >= MAX_SAVE_SLOTS) return 0;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetCharacterExpToNext(id);
+}
+
+unsigned int SavemapManager::GetSlotCharacterLimitLevel(
+  const unsigned int slot, const unsigned int id
+){
+    if (slot >= MAX_SAVE_SLOTS) return 0;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetCharacterLimitLevel(id);
+}
+
+unsigned int SavemapManager::GetSlotCharacterLimitBar(
+  const unsigned int slot, const unsigned int id
+){
+    if (slot >= MAX_SAVE_SLOTS) return 0;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetCharacterLimitBar(id);
+}
+
+unsigned int SavemapManager::GetSlotCharacterWeaponId(
+  const unsigned int slot, const unsigned int id
+){
+    if (slot >= MAX_SAVE_SLOTS) return 0;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetCharacterWeaponId(id);
+}
+
+unsigned int SavemapManager::GetSlotCharacterArmorId(
+  const unsigned int slot, const unsigned int id
+){
+    if (slot >= MAX_SAVE_SLOTS) return 0;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetCharacterArmorId(id);
+}
+
+int SavemapManager::GetSlotCharacterAccessoryId(const unsigned int slot, const unsigned int id){
+    if (slot >= MAX_SAVE_SLOTS) return -1;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetCharacterAccessoryId(id);
+}
+
+unsigned int SavemapManager::GetSlotCharacterStatBase(
+  const unsigned int slot, const unsigned int id, const unsigned int stat
+){
+    if (slot >= MAX_SAVE_SLOTS) return 0;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetCharacterStatBase(id, stat);
+}
+
+unsigned int SavemapManager::GetSlotCharacterStatExtra(
+  const unsigned int slot, const unsigned int id, const unsigned int stat
+){
+    if (slot >= MAX_SAVE_SLOTS) return 0;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetCharacterStatExtra(id, stat);
+}
+
+unsigned int SavemapManager::GetSlotCharacterLimitUses(
+  const unsigned int slot, const unsigned int id, const unsigned int level
+){
+    if (slot >= MAX_SAVE_SLOTS) return 0;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetCharacterLimitUses(id, level);
+}
+
+bool SavemapManager::IsSlotCharacterLimitLearned(
+  const unsigned int slot, const unsigned int id, const unsigned int level, const unsigned int tech
+){
+    if (slot >= MAX_SAVE_SLOTS) return false;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->IsCharacterLimitLearned(id, level, tech);
+}
+
+int SavemapManager::GetSlotCharacterMateriaId(
+  const unsigned int slot, const unsigned int id, const bool weapon, const unsigned int pos
+){
+    if (slot >= MAX_SAVE_SLOTS) return -1;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetCharacterMateriaId(id, weapon, pos);
+}
+
+unsigned int SavemapManager::GetSlotCharacterMateriaAp(
+  const unsigned int slot, const unsigned int id, const bool weapon, const unsigned int pos
+ ){
+    if (slot >= MAX_SAVE_SLOTS) return 0;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetCharacterMateriaAp(id, weapon, pos);
+}
+
+bool SavemapManager::IsSlotCharacterMateriaESkill(
+  const unsigned int slot, const unsigned int id, const bool weapon, const unsigned int pos
+){
+    if (slot >= MAX_SAVE_SLOTS) return false;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->IsCharacterMateriaESkill(id, weapon, pos);
+}
+
+bool SavemapManager::IsSlotCharacterMateriaESkillLearned(
+  const unsigned int slot, const unsigned int id, const bool weapon,
+  const unsigned int pos, const unsigned int skill
+){
+    if (slot >= MAX_SAVE_SLOTS) return false;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->IsCharacterMateriaESkillLearned(id, weapon, pos, skill);
+}
+
+int SavemapManager::GetSlotData(
+  const unsigned int slot, const unsigned int bank, const unsigned int address
+){
+    if (slot >= MAX_SAVE_SLOTS) return false;
+    if (savemaps_read_ == false) ReadSavemaps();
+    return saved_savemaps_[slot]->GetData(bank, address);
 }
 
 

+ 12 - 13
data/data/screens/begin_menu/begin_menu.xml

@@ -2,19 +2,18 @@
     <widget name="Container" width="368" height="240" origin_x="50%" origin_y="50%" align="center" valign="middle" scale="2.61 3" visible="true">
         <sprite name="Sword" image="images/other/begin_menu.png" x="111" y="84" width="170" height="150" visible="true" />
         <sprite name="Cursor" image="images/icons/cursor.png" x="132" y="99" width="24" height="16" visible="true">
-            <animation name="Position1" length="0" y="0:99" />
-            <animation name="Position2" length="0" y="0:111" />
-            <animation name="Position3" length="0" y="0:123" />
-            <animation name="Position4" length="0" y="0:135" />
-            <animation name="Position5" length="0" y="0:147" />
-            <animation name="Position6" length="0" y="0:160" />
+            <animation name="Position1" length="0" y="0:80" />
+            <animation name="Position2" length="0" y="0:92" />
+            <animation name="Position3" length="0" y="0:110" />
+            <animation name="Position4" length="0" y="0:122" />
+            <animation name="Position5" length="0" y="0:134" />
+            <animation name="Position6" length="0" y="0:146" />
         </sprite>
-        <text_area name="Text1" x="158" y="99" text_name="BeginMenuNewGame" font="FFVIIFont" visible="true" />
-        <text_area name="Text2" x="158" y="111" text_name="BeginMenu1" font="FFVIIFont" visible="true" />
-        <text_area name="Text3" x="158" y="123" text_name="BeginMenu2" font="FFVIIFont" visible="true" />
-        <text_area name="Text4" x="158" y="135" text_name="BeginMenu3" font="FFVIIFont" visible="true" />
-        <text_area name="Text5" x="158" y="147" text_name="BeginMenu4" font="FFVIIFont" visible="true" />
-        <text_area name="Text6" x="158" y="160" text_name="BeginMenu5" font="FFVIIFont" visible="true" />
-
+        <text_area name="Text1" x="158" y="80" text_name="BeginMenuNewGame" font="FFVIIFont" visible="true" />
+        <text_area name="Text2" x="158" y="92" text_name="BeginMenuLoadGame" font="FFVIIFont" visible="true" />
+        <text_area name="Text3" x="158" y="110" text_name="BeginMenu2" font="FFVIIFont" visible="true" />
+        <text_area name="Text4" x="158" y="122" text_name="BeginMenu3" font="FFVIIFont" visible="true" />
+        <text_area name="Text5" x="158" y="134" text_name="BeginMenu4" font="FFVIIFont" visible="true" />
+        <text_area name="Text6" x="158" y="146" text_name="BeginMenu5" font="FFVIIFont" visible="true" />
     </widget>
 </screen>

+ 5 - 3
data/data/scripts/data.lua

@@ -66,6 +66,8 @@ Game = {
     Summon_Names = {},
 }
 
+ControlKey = "";
+
 --- Playable characters
 Characters = {}
 for i = 1, 11 do
@@ -254,11 +256,11 @@ end
 --
 -- @todo Delete this, and implement bit operations over Banks.
 BitBanks = {}
-for i = 0, 14 do
+for i = 0, 15 do
     BitBanks[i] = {}
-    for j = 0, 254 do
+    for j = 0, 255 do
         BitBanks[i][j] = {}
-        for k = 0, 7 do
+        for k = 0, 8 do
             BitBanks[i][j][k] = 0
         end
     end

+ 56 - 51
data/data/scripts/menu/begin_menu.lua

@@ -1,48 +1,54 @@
 if UiContainer == nil then UiContainer = {} end
 
-
-
+--- The begin menu
 UiContainer.BeginMenu = {
-    position = 1,
-    position_total = 6,
 
+    --- Current cursor position
+    position = 1,
 
+    -- Max cursor position
+    position_total = 6,
 
-    on_start = function( self )
-        local cursor = ui_manager:get_widget( "BeginMenu.Container.Cursor" )
-        cursor:set_default_animation( "Position" .. self.position )
+    --- Run when the menu is created.
+    --
+    -- Sets this menu as the one beind displayed.
+    on_start = function(self)
+        UiContainer.current_menu = "begin"
+        local cursor = ui_manager:get_widget("BeginMenu.Container.Cursor")
+        cursor:set_default_animation("Position" .. self.position)
         return 0
     end,
 
 
-
-    on_button = function( self, button, event )
-
-        if ui_manager:get_widget( "BeginMenu" ):is_visible() ~= false then
-            local cursor = ui_manager:get_widget( "BeginMenu.Container.Cursor" )
-
+    --- Handles button events.
+    --
+    -- Handles directional Up, Down and Enter keys.
+    -- @param button Pressed button string key. "Up", "Left", "Enter" and "Escape" are handled.
+    -- @param event Trigger event. Normally, "Press".
+    on_button = function(self, button, event)
+        if UiContainer.current_menu == "begin" then
+            local cursor = ui_manager:get_widget("BeginMenu.Container.Cursor")
             if button == "Enter" and event == "Press" then
-                if self.position == 1 then
+                if self.position == 1 then -- New game
                     audio_manager:play_sound("Window")
-                    load_field_map_request( "md1stin", "" )
-                    console( "camera_free false" )
-                    --console( "debug_walkmesh true" )
-                    script:request_end_sync( Script.UI, "BeginMenu", "hide", 0 )
-                    MenuSettings.pause_available = true
-                elseif self.position == 2 then
-                    script:request_end_sync( Script.UI, "BeginMenu", "hide", 0 )
-                    console( "camera_free true" )
-                    console( "debug_walkmesh true" )
-                    map( "test_3" )
+                    generate_control_key()
+                    load_field_map_request("md1stin", "")
+                    console("camera_free false")
+                    --console("debug_walkmesh true")
+                    script:request_end_sync(Script.UI, "BeginMenu", "hide", 0)
                     MenuSettings.pause_available = true
+                elseif self.position == 2 then -- Load, show save menu.
+                    audio_manager:play_sound("Cursor")
+                    UiContainer.SaveMenu.operation = "load"
+                    script:request_end_sync(Script.UI, "SaveMenu", "show", 0)
                 elseif self.position == 3 then
                     -- NMKIN_3 START
                     Data.progress_game = 27
                     load_field_map_request("nmkin_3", "")
-                    console( "camera_free false" )
-                    console( "debug_walkmesh true" )
+                    console("camera_free false")
+                    console("debug_walkmesh true")
                     script:wait(1)
-                    script:request_end_sync( Script.UI, "BeginMenu", "hide", 0 )
+                    script:request_end_sync(Script.UI, "BeginMenu", "hide", 0)
                     entity_manager:get_entity("Cloud"):set_position(-1.090750, 15.310307, 17.281244)
                     entity_manager:set_player_entity("Cloud")
                     script:wait(1)
@@ -59,7 +65,7 @@ UiContainer.BeginMenu = {
                     console("camera_free false")
                     console("debug_walkmesh true")
                     script:wait(1.5)
-                    script:request_end_sync( Script.UI, "BeginMenu", "hide", 0 )
+                    script:request_end_sync(Script.UI, "BeginMenu", "hide", 0)
                     entity_manager:get_entity("Cloud"):set_position(-0.820312, 0.500000, 17.281244)
                     entity_manager:set_player_entity("Cloud")
                     set_party(0, 1, 4)
@@ -72,20 +78,20 @@ UiContainer.BeginMenu = {
                     MenuSettings.pause_available = true]]
                     -- NMKIN_4 END
                 elseif self.position == 4 then
-                    script:request_end_sync( Script.UI, "BeginMenu", "hide", 0 )
-                    console( "camera_free true" )
-                    console( "debug_walkmesh true" )
-                    map( "test_2" )
+                    script:request_end_sync(Script.UI, "BeginMenu", "hide", 0)
+                    console("camera_free true")
+                    console("debug_walkmesh true")
+                    map("test_2")
                     MenuSettings.pause_available = true
                 elseif self.position == 5 then
-                    script:request_end_sync( Script.UI, "BeginMenu", "hide", 0 )
-                    console( "camera_free true" )
+                    script:request_end_sync(Script.UI, "BeginMenu", "hide", 0)
+                    console("camera_free true")
                     world_map_module:init()
                 elseif self.position == 6 then
-                    load_field_map_request( "startmap", "" )
-                    console( "camera_free false" )
-                    console( "debug_walkmesh false" )
-                    script:request_end_sync( Script.UI, "BeginMenu", "hide", 0 )
+                    load_field_map_request("startmap", "")
+                    console("camera_free false")
+                    console("debug_walkmesh false")
+                    script:request_end_sync(Script.UI, "BeginMenu", "hide", 0)
                     MenuSettings.pause_available = true
                 end
             elseif button == "Down" then
@@ -94,33 +100,32 @@ UiContainer.BeginMenu = {
                 if self.position > self.position_total then
                     self.position = 1;
                 end
-                cursor:set_default_animation( "Position" .. self.position )
+                cursor:set_default_animation("Position" .. self.position)
             elseif button == "Up" then
                 audio_manager:play_sound("Cursor")
                 self.position = self.position - 1
                 if self.position <= 0 then
                     self.position = self.position_total;
                 end
-                cursor:set_default_animation( "Position" .. self.position )
+                cursor:set_default_animation("Position" .. self.position)
             end
         end
-
         return 0
     end,
 
-
-
-    show = function( self )
-        ui_manager:get_widget( "BeginMenu" ):set_visible( true )
-
+    --- Opens the save menu.
+    show = function(self)
+        UiContainer.current_menu = "begin"
+        ui_manager:get_widget("BeginMenu"):set_visible(true)
         return 0;
     end,
 
-
-
-    hide = function( self )
-        ui_manager:get_widget( "BeginMenu" ):set_visible( false )
-
+    --- Hiddens the begin menu.
+    --
+    -- It doesn't do anything else.
+    hide = function(self)
+        UiContainer.current_menu = ""
+        ui_manager:get_widget("BeginMenu"):set_visible(false)
         return 0;
     end,
 }

+ 40 - 23
data/data/scripts/menu/save_menu.lua

@@ -38,7 +38,6 @@ UiContainer.SaveMenu = {
                     script:request_end_sync(Script.UI, "SaveMenu", "hide", 0)
                 elseif button == "Enter" then
                     self.action(self, self.first_visible - 1 + self.position)
-                    audio_manager:play_sound("Cursor")
                 elseif button == "Down" then
                     if self.position < self.position_total and self.first_visible + self.position < self.max_slots then
                         -- Move cursor down
@@ -85,6 +84,8 @@ UiContainer.SaveMenu = {
             print("before calling show()")
             return 0
         end
+        UiContainer.current_menu = "save"
+        UiContainer.current_submenu = ""
         if self.operation == "load" then
             ui_manager:get_widget("SaveMenu.Container.TopBar.DescSave"):set_visible(false)
             ui_manager:get_widget("SaveMenu.Container.TopBar.DescLoad"):set_visible(true)
@@ -107,22 +108,27 @@ UiContainer.SaveMenu = {
 
     populate_slots = function(self)
         for s = 1, 3 do
-            local slot = self.first_visible - 1 + s -- 0-index
-            if savemap_manager:slot_is_empty(slot) == true then
+            local slot = self.first_visible + s - 2 -- 0-index
+            if savemap_manager:is_slot_empty(slot) == true then
                 ui_manager:get_widget("SaveMenu.Container.Slot" .. tostring(s) .. ".Slot"):set_visible(false)
                 ui_manager:get_widget("SaveMenu.Container.Slot" .. tostring(s) .. ".Empty"):set_visible(true)
             else
                 local slot_id = "SaveMenu.Container.Slot" .. tostring(s) .. ".Slot."
-                local info = self.split_preview_data(savemap_manager:get_preview_data(slot))
-                ui_manager:get_widget(slot_id .. "TimeMoney.Money"):set_text(UiContainer.pad_value(info[3], 7))
-                local time = UiContainer.pad_value(math.floor(info[4] / 3600), 3) .. ":" .. UiContainer.zero_pad_value(math.floor((info[4] % 3600) / 60), 2)
+                ui_manager:get_widget(slot_id .. "TimeMoney.Money"):set_text(UiContainer.pad_value(savemap_manager:get_slot_money(slot), 7))
+                local seconds = savemap_manager:get_slot_game_time(slot)
+                local time = UiContainer.pad_value(math.floor(seconds / 3600), 3) .. ":" .. UiContainer.zero_pad_value(math.floor((seconds % 3600) / 60), 2)
                 ui_manager:get_widget(slot_id .. "TimeMoney.Time"):set_text(time)
-                ui_manager:get_widget(slot_id .. "Location.Name"):set_text(tostring(info[5]))
-                ui_manager:get_widget(slot_id .. "Name"):set_text(tostring(info[6]))
-                ui_manager:get_widget(slot_id .. "LvNumber"):set_text(UiContainer.pad_value(info[7], 3))
+                ui_manager:get_widget(slot_id .. "Location.Name"):set_text(savemap_manager:get_slot_location_name(slot))
+                local save_party = {
+                    [1] = savemap_manager:get_slot_party_member(slot, 0),
+                    [2] = savemap_manager:get_slot_party_member(slot, 1),
+                    [3] = savemap_manager:get_slot_party_member(slot, 2)
+                }
+                ui_manager:get_widget(slot_id .. "Name"):set_text(savemap_manager:get_slot_character_name(slot, save_party[1]))
+                ui_manager:get_widget(slot_id .. "LvNumber"):set_text(UiContainer.pad_value(savemap_manager:get_slot_character_level(slot, save_party[1]), 3))
                 for c = 1, 3 do
-                    if tonumber(info[7 + c]) ~= -1 and Characters[info[7 + c] + 1] ~= nil then
-                        ui_manager:get_widget(slot_id .. "Party.Portrait" .. tostring(c)):set_image("images/characters/" .. tostring(info[7 + c]) .. ".png")
+                    if save_party[c] ~= -1 and Characters[save_party[c] + 1] ~= nil then
+                        ui_manager:get_widget(slot_id .. "Party.Portrait" .. tostring(c)):set_image("images/characters/" .. tostring(save_party[c]) .. ".png")
                         ui_manager:get_widget(slot_id .. "Party.Portrait" .. tostring(c)):set_visible(true)
                     else
                         ui_manager:get_widget(slot_id .. "Party.Portrait" .. tostring(c)):set_visible(false)
@@ -134,24 +140,35 @@ UiContainer.SaveMenu = {
         end
     end,
 
-    split_preview_data = function(data)
-        local sep = "#"
-        local t={}
-        for str in string.gmatch(data, "([^"..sep.."]+)") do
-            table.insert(t, str)
-        end
-        return t
-    end,
-
-
     action = function(self, slot)
-        print("ACTION " .. self.operation .. " ON SLOT " .. tostring(slot))
+        if self.operation == "save" then
+            if savemap_manager:is_slot_empty(slot - 1) == false and ControlKey ~= savemap_manager:get_slot_control_key(slot - 1) then
+                -- TODO: Confirmation dialog
+                print("OVERRIDE ANOTHER SAVE")
+                save_game(slot - 1, true)
+                audio_manager:play_sound("Cursor")
+                self.populate_slots(self)
+            else
+                save_game(slot - 1, true)
+                audio_manager:play_sound("Cursor")
+                self.populate_slots(self)
+            end
+        elseif self.operation == "load" then
+            audio_manager:play_sound("Window")
+            script:request_end_sync(Script.UI, "SaveMenu", "hide", 0)
+            script:request_end_sync(Script.UI, "BeginMenu", "hide", 0)
+            load_game(slot - 1)
+        end
     end,
 
     --- Hides the item menu and goes back to the main menu.
     hide = function(self)
         ui_manager:get_widget("SaveMenu"):set_visible(false)
-        UiContainer.current_menu = "main"
+        if self.operation == "load" then
+            UiContainer.current_menu = "begin"
+        else
+            UiContainer.current_menu = "main"
+        end
         UiContainer.current_submenu = ""
         savemap_manager:release()
         return 0;

+ 173 - 2
data/data/scripts/save.lua

@@ -1,4 +1,11 @@
-save_game = function(slot)
+generate_control_key = function()
+    ControlKey = ""
+    for i = 1, 8 do
+        ControlKey = ControlKey .. string.char(math.random(97, 97 + 25))
+    end
+end
+
+save_game = function(slot, force)
     savemap_manager:set_control_key("CONTROL_EXAMPLE") -- TODO Actual data
     savemap_manager:set_window_colours(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) -- TODO Actual data
     savemap_manager:set_money(Inventory.money)
@@ -79,5 +86,169 @@ save_game = function(slot)
 
         end
     end
-    savemap_manager:save(slot, false)
+    savemap_manager:save(slot, force or true)
+end
+
+load_game = function(slot)
+    print("LAOD SLOT " .. tostring(slot))
+    -- Populate banks
+    for b = 0, 14 do
+        for a = 0, 254 do
+            Banks[b][a] = savemap_manager:get_slot_data(slot, b, a)
+        end
+    end
+    -- TODO: Window colours
+    Inventory.money = savemap_manager:get_slot_money(slot)
+    -- TODO: Game time
+    -- TODO: Countdown
+    for p = 1, 3 do
+        Party[p] = savemap_manager:get_slot_party_member(slot, p - 1)
+    end
+    for i = 0, MAX_INVENTORY_SLOTS do
+        Inventory[i] = {item = 0, quantity = 0}
+        Inventory[i].quantity = savemap_manager:get_slot_item_at_pos_qty(slot, i)
+        if Inventory[i].quantity > 0 then
+            Inventory[i].id = savemap_manager:get_slot_item_at_pos_id(slot, i)
+        else
+            Inventory[i] = nil
+        end
+    end
+    for i = 0, MAX_MATERIA_SLOTS do
+        Materia[i] = {id = -1, ap = 0}
+        Materia[i].id = savemap_manager:get_slot_materia_at_pos_id(slot, i)
+        if Materia[i].id >= 0 then
+            Materia[i].ap = savemap_manager:get_slot_materia_at_pos_ap(slot, i)
+            if Materia[i].id == Materia.ENEMY_SKILL_ID then
+                Materia[i].ap = 0
+                Materia[i].skills = {}
+                for s = 1, 24 do
+                    Materia[i].skills[s] = savemap_manager:is_slot_materia_at_pos_e_skill_learned(slot, i, s - 1)
+                end
+            end
+        else
+            Materia[i] = nil
+        end
+    end
+    -- TODO: Stash (same as materia)
+    for i = 0, MAX_KEY_SLOTS do
+        Inventory.key[i] = savemap_manager:get_slot_key_item(slot, i)
+    end
+    -- Characters
+    for c = 0, 11 do
+        Characters[c].char_id = savemap_manager:get_slot_character_char_id(slot, c)
+        if Characters[c].char_id == -1 then
+            Characters[c] = nil
+        else
+            Characters[c] = {}
+            Characters[c].name = savemap_manager:get_slot_character_name(slot, c)
+            Characters[c].level = savemap_manager:get_slot_character_level(slot, c)
+            Characters[c].enabled = savemap_manager:is_slot_character_enabled(slot, c)
+            Characters[c].locked = savemap_manager:is_slot_character_locked(slot, c)
+            Characters[c].kills = savemap_manager:get_slot_character_kills(slot, c)
+            Characters[c].back_row = savemap_manager:is_slot_character_back_row(slot, c)
+            Characters[c].exp = savemap_manager:get_slot_character_exp(slot, c)
+            Characters[c].exp_to_next = savemap_manager:get_slot_character_exp_to_next(slot, c)
+            Characters[c].stats = {}
+            Characters[c].stats.str = {
+                base = savemap_manager:get_slot_character_stat_base(slot, c, 0),
+                bonus = savemap_manager:get_slot_character_stat_extra(slot, c, 0),
+                total = 0
+            }
+            Characters[c].stats.vit = {
+                base = savemap_manager:get_slot_character_stat_base(slot, c, 1),
+                bonus = savemap_manager:get_slot_character_stat_extra(slot, c, 1),
+                total = 0
+            }
+            Characters[c].stats.mag = {
+                base = savemap_manager:get_slot_character_stat_base(slot, c, 2),
+                bonus = savemap_manager:get_slot_character_stat_extra(slot, c, 2),
+                total = 0
+            }
+            Characters[c].stats.spr = {
+                base = savemap_manager:get_slot_character_stat_base(slot, c, 3),
+                bonus = savemap_manager:get_slot_character_stat_extra(slot, c, 3),
+                total = 0
+            }
+            Characters[c].stats.dex = {
+                base = savemap_manager:get_slot_character_stat_base(slot, c, 4),
+                bonus = savemap_manager:get_slot_character_stat_extra(slot, c, 4),
+                total = 0
+            }
+            Characters[c].stats.lck = {
+                base = savemap_manager:get_slot_character_stat_base(slot, c, 5),
+                bonus = savemap_manager:get_slot_character_stat_extra(slot, c, 5),
+                total = 0
+            }
+            Characters[c].stats.hp = {
+                current = savemap_manager:get_slot_character_stat_extra(slot, c, 6),
+                base = savemap_manager:get_slot_character_stat_base(slot, c, 6),
+                max = 65535
+            }
+            Characters[c].stats.mp = {
+                current = savemap_manager:get_slot_character_stat_extra(slot, c, 7),
+                base = savemap_manager:get_slot_character_stat_base(slot, c, 7),
+                max = 65535
+            }
+            Characters[c].limit = {}
+            Characters[c].limit.current = savemap_manager:get_slot_character_limit_level(slot, c)
+            Characters[c].limit.bar = savemap_manager:get_slot_character_limit_bar(slot, c)
+            Characters[c].limit.learned = {}
+            Characters[c].limit.uses = {}
+            for l = 1, 4 do
+                Characters[c].limit.learned[l] = {
+                    [1] = savemap_manager:is_slot_character_limit_learned(slot, c, l, 0),
+                    [2] = savemap_manager:is_slot_character_limit_learned(slot, c, l, 1)
+                }
+                Characters[c].limit.uses[l] = savemap_manager:get_slot_character_limit_uses(slot, c, l)
+            end
+            Characters[c].accessory = savemap_manager:get_slot_character_accessory_id(slot, c)
+            Characters[c].weapon = {}
+            Characters[c].armor = {}
+            Characters[c].weapon.id = savemap_manager:get_slot_character_weapon_id(slot, c)
+            Characters[c].armor.id = savemap_manager:get_slot_character_armor_id(slot, c)
+            Characters[c].weapon.materia = {}
+            Characters[c].armor.materia = {}
+            for i = 0, 8 do
+                Characters[c].weapon.materia[i] = {id = -1, ap = 0}
+                Characters[c].armor.materia[i] = {id = -1, ap = 0}
+                Characters[c].weapon.materia[i].id = savemap_manager:get_slot_character_materia_id(slot, c, true, i)
+                Characters[c].armor.materia[i].id = savemap_manager:get_slot_character_materia_id(slot, c, false, i)
+                if Characters[c].weapon.materia[i].id >= 0 then
+                    Characters[c].weapon.materia[i].ap = savemap_manager:get_slot_character_materia_ap(slot, i, true, i)
+                    if Characters[c].weapon.materia[i].id == Materia.ENEMY_SKILL_ID then
+                        Characters[c].weapon.materia[i].ap = 0
+                        Characters[c].weapon.materia[i].skills = {}
+                        for s = 1, 24 do
+                            Characters[c].weapon.materia[i].skills[s] = savemap_manager:is_slot_character_materia_e_skill_learned(slot, i, c, true, s - 1)
+                        end
+                    end
+                else
+                    Characters[c].weapon.materia[i] = nil
+                end
+                if Characters[c].armor.materia[i].id >= 0 then
+                    Characters[c].armor.materia[i].ap = savemap_manager:get_slot_character_materia_ap(slot, i, false, i)
+                    if Characters[c].armor.materia[i].id == Materia.ENEMY_SKILL_ID then
+                        Characters[c].armor.materia[i].ap = 0
+                        Characters[c].armor.materia[i].skills = {}
+                        for s = 1, 24 do
+                            Characters[c].armor.materia[i].skills[s] = savemap_manager:is_slot_character_materia_e_skill_learned(slot, i, c, false, s - 1)
+                        end
+                    end
+                else
+                    Characters[c].armor.materia[i] = nil
+                end
+            end
+            -- TODO: Status
+            Characters[c].status = {}
+            print("RECALC " .. tostring(c))
+            Characters.recalculate_stats(c)
+        end
+
+    end
+    -- TODO: Settings
+    -- TODO: Location
+    -- TODO: Update character stats
+    -- TODO: Handle world map when implemented
+    load_field_map_request(savemap_manager:get_slot_location_field(slot), "")
+    MenuSettings.pause_available = true
 end

+ 1 - 0
data/data/scripts/system.lua

@@ -1,4 +1,5 @@
 MAX_INVENTORY_SLOTS = 320
+MAX_KEY_SLOTS = 50
 MAX_MATERIA_SLOTS = 200
 
 --- Export character names to the text manager.

+ 17 - 5
data/data/texts/english/menu.xml

@@ -21,11 +21,12 @@
     <text name="MateriaEncountersChocobo">Chocobo</text>
 
     <text name="BeginMenuNewGame">NEW GAME</text>
-    <text name="BeginMenu1">DEBUG: Battle map</text>
-    <text name="BeginMenu2">DEBUG: Quick map</text>
-    <text name="BeginMenu3">DEBUG: Entity testarea</text>
-    <text name="BeginMenu4">DEBUG: World map test</text>
-    <text name="BeginMenu5">DEBUG: Debug Room</text>
+    <text name="BeginMenuLoadGame">LOAD GAME</text>
+    <text name="BeginMenu1"><colour value="0.5 0.5 0.5">DEBUG: Battle map</colour></text>
+    <text name="BeginMenu2"><colour value="0.5 0.5 0.5">DEBUG: Quick map</colour></text>
+    <text name="BeginMenu3"><colour value="0.5 0.5 0.5">DEBUG: Entity testarea</colour></text>
+    <text name="BeginMenu4"><colour value="0.5 0.5 0.5">DEBUG: World map test</colour></text>
+    <text name="BeginMenu5"><colour value="0.5 0.5 0.5">DEBUG: Debug Room</colour></text>
 
     <text name="PauseMenuHeader">Paused</text>
     <text name="PauseMenuText">Are you want to quit?</text>
@@ -102,6 +103,17 @@
     <text name="NameMenuConfirm">Confirm</text>
     <text name="NameMenuConfirmMsg">Confirm name</text>
 
+    <text name="SaveMenuSave">Save</text>
+    <text name="SaveMenuLoad">Load</text>
+    <text name="SaveMenuLevel"><colour value="0 0.8 1">Level</colour></text>
+    <text name="SaveMenuTime">Time</text>
+    <text name="SaveMenuMoney">Gil</text>
+    <text name="SaveMenuEmptySlot"><colour value="0.6 0.6 0.6">Empty slot</colour></text>
+    <text name="SaveMenuTitleSave">Save</text>
+    <text name="SaveMenuTitleLoad">Load</text>
+    <text name="SaveMenuDescSave">Select a slot to save</text>
+    <text name="SaveMenuDescLoad">Select a game to load</text>
+
     <text name="CharacterDataName">#Name#</text>
     <text name="CharacterDataLv">LV</text>
     <text name="CharacterDataLvNumber"> 0</text>