Finished saving + editing - Monsters/Items/characters/

Will add Egg fragments and then release.
This commit is contained in:
secXsQuared1995 2016-10-19 05:35:38 -04:00
parent 7ae1cde029
commit f0cecf442d
10 changed files with 879 additions and 86 deletions

View File

@ -10,15 +10,5 @@ namespace MHSEC_G
{
public partial class App : Application
{
private Model model;
public Model get_model()
{
return model;
}
public void set_model(Model model)
{
}
}
}

View File

@ -1,4 +1,5 @@
using System.ComponentModel;
using System.Windows;
using MHSEC_G.Annotations;
namespace MHSEC_G
@ -6,46 +7,88 @@ namespace MHSEC_G
public class Character : INotifyPropertyChanged
{
private const uint OFFSETA_CHAR_NAME = 0x9DA0;
private const uint LENGTH_CHAR_NAME = 6;
private const uint LENGTH_CHAR_NAME = 5;
private const uint OFFSETA_CHAR_MONEY = 0x5B404;
private const uint OFFSETA_CHAR_EXP = 0x9E68;
private const uint OFFSETA_CHAR_LEVEL = 0x9E64;
public const uint LIMIT_LEVEL = 99;
public const uint LIMIT_MONEY = 9999999;
public const uint LIMIT_EXP = 25165822;
private uint _char_level;
public uint char_level
private readonly Model _model;
public uint level
{
get { return _char_level; }
set { _char_level = value; OnPropertyChanged(nameof(char_level)); }
get { return Model.byte_to_uint(_model.save_file[OFFSETA_CHAR_LEVEL]); }
set
{
if (value <= LIMIT_LEVEL)
{
Model.write_byte(_model.save_file, OFFSETA_CHAR_LEVEL, value);
}
else
{
MessageBox.Show("Level must be less than " + LIMIT_LEVEL, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(level));
}
}
private uint _char_exp;
public uint char_exp
public uint exp
{
get { return _char_exp; }
set { _char_exp = value; OnPropertyChanged(nameof(char_exp)); }
get { return Model.byte_to_uint32_le(_model.save_file, OFFSETA_CHAR_EXP); }
set
{
if (value <= LIMIT_EXP)
{
Model.write_uint32_le(_model.save_file, OFFSETA_CHAR_EXP, value);
}
else
{
MessageBox.Show("Exp must be less than " + LIMIT_EXP, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(exp));
}
}
private uint _char_money;
public uint char_money
public uint money
{
get { return _char_money; }
set { _char_money = value; OnPropertyChanged(nameof(char_money)); }
get { return Model.byte_to_uint32_le(_model.save_file, OFFSETA_CHAR_MONEY); }
set
{
if (value <= LIMIT_MONEY)
{
Model.write_uint32_le(_model.save_file, OFFSETA_CHAR_MONEY, value);
}
else
{
MessageBox.Show("Money must be less than " + LIMIT_MONEY, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(money));
}
}
private string _char_name;
public string char_name
public string name
{
get { return _char_name; }
set { _char_name = value; OnPropertyChanged(nameof(char_name)); }
get { return Model.read_unicode_string(_model.save_file, OFFSETA_CHAR_NAME, LENGTH_CHAR_NAME); }
set
{
if (value.Length <= LENGTH_CHAR_NAME && value.Length > 0)
{
Model.write_unicode_string(_model.save_file, OFFSETA_CHAR_NAME, value, LENGTH_CHAR_NAME);
}
else
{
MessageBox.Show("Name must be 1-6 characters.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(name));
}
}
public Character(byte[] save_data)
public Character(Model model)
{
_char_level = Model.byte_to_uint(save_data[OFFSETA_CHAR_LEVEL]);
_char_exp = Model.byte_to_uint32_le(save_data, OFFSETA_CHAR_EXP);
_char_money = Model.byte_to_uint32_le(save_data, OFFSETA_CHAR_MONEY);
_char_name = Model.read_unicode_string(save_data, OFFSETA_CHAR_NAME, LENGTH_CHAR_NAME);
_model = model;
}
public event PropertyChangedEventHandler PropertyChanged;

View File

@ -1,11 +1,132 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using MHSEC_G.Annotations;
namespace MHSEC_G
{
class Item
public class Item : INotifyPropertyChanged
{
private static readonly uint OFFSETA_ITEM_BOX = 0x10;
private static readonly uint SIZE_ITEM = 0x8;
private static readonly uint OFFSETR_ITEM_ID = 0x0;
private static readonly uint OFFSETR_ITEM_COUNT = 0x2;
private static readonly uint OFFSETA_ITEM_BOX_END = 0x2EE7;
private static readonly string ID_MAPPING_FILE_NAME = "C:\\Users\\hyper\\Desktop\\idmap.txt";
private static readonly Dictionary<uint, uint> OFFSET_ID_MAPPING = new Dictionary<uint, uint>();
private static readonly Dictionary<uint, string> OFFSET_NAME_MAPPING = new Dictionary<uint, string>();
private readonly uint _offset;
private readonly Model _model;
public string name
{
get {
string name = "Unknown";
if (OFFSET_NAME_MAPPING.ContainsKey(_offset))
{
name = OFFSET_NAME_MAPPING[_offset];
}
return name;
}
}
public uint count
{
get { return Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_ITEM_COUNT); }
set
{
if (value <= 999)
{
Model.write_uint16_le(_model.save_file, _offset + OFFSETR_ITEM_COUNT, value);
}
else
{
MessageBox.Show("Quantity must be less than 999.","Error",MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(count));
}
}
public uint id
{
get { return Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_ITEM_ID); }
}
public Item(uint offset, Model model)
{
_offset = offset;
_model = model;
}
public static List<Item> read_all_items(Model model)
{
byte[] buffer = model.save_file;
List<Item> ret = new List<Item>();
for (uint offset = OFFSETA_ITEM_BOX; offset < OFFSETA_ITEM_BOX_END; offset += SIZE_ITEM)
{
string name = "Unknown";
uint item_id = Model.byte_to_uint16_le(buffer, offset + OFFSETR_ITEM_ID);
if (item_id == 0)
{
// if not obtained yet
if (!OFFSET_ID_MAPPING.ContainsKey(offset))
{
// well we dont know the id to this offset either. just ignore!
// continue
continue;
}
}
else
{
// already obtained
// validate
if (OFFSET_ID_MAPPING.ContainsKey(offset))
{
if (item_id != OFFSET_ID_MAPPING[offset])
{
throw new SystemException("Item offset and ID do not correspond.");
}
}
}
// valid offset
ret.Add(new Item(offset, model));
}
return ret;
}
public static void read_item_mappings()
{
string line;
System.IO.StreamReader file = new System.IO.StreamReader(ID_MAPPING_FILE_NAME);
while ((line = file.ReadLine()) != null)
{
if (line.Length == 0)
continue;
string[] eachline = line.Split('\t');
if (eachline.Length != 3)
throw new SystemException("Item mapping file is corrupted.");
OFFSET_ID_MAPPING.Add(UInt32.Parse(eachline[0], System.Globalization.NumberStyles.HexNumber), UInt32.Parse(eachline[1], System.Globalization.NumberStyles.HexNumber));
OFFSET_NAME_MAPPING.Add(UInt32.Parse(eachline[0], System.Globalization.NumberStyles.HexNumber), eachline[2]);
}
file.Close();
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@ -98,6 +98,9 @@
</None>
<AppDesigner Include="Properties\" />
</ItemGroup>
<ItemGroup>
<Resource Include="idmap.txt" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -15,25 +15,91 @@
<Label x:Name="label_money" Content="Money" HorizontalAlignment="Left" Margin="10,40,0,0" VerticalAlignment="Top"/>
<Label x:Name="label_leve" Content="Level" HorizontalAlignment="Left" Margin="10,70,0,0" VerticalAlignment="Top"/>
<Label x:Name="label_exp" Content="Exp" HorizontalAlignment="Left" Margin="10,100,0,0" VerticalAlignment="Top"/>
<TextBox x:Name="textbox_name" HorizontalAlignment="Left" Height="22" Margin="61,14,0,0" TextWrapping="NoWrap" VerticalAlignment="Top" Width="120" Text="{Binding model.character.char_name}"/>
<TextBox x:Name="textbox_money" HorizontalAlignment="Left" Height="22" Margin="61,44,0,0" TextWrapping="NoWrap" VerticalAlignment="Top" Width="120" Text="{Binding model.character.char_money}"/>
<TextBox x:Name="textbox_level" HorizontalAlignment="Left" Height="22" Margin="61,74,0,0" TextWrapping="NoWrap" VerticalAlignment="Top" Width="120" Text="{Binding model.character.char_level}"/>
<TextBox x:Name="textbox_exp" HorizontalAlignment="Left" Height="22" Margin="61,104,0,0" TextWrapping="NoWrap" VerticalAlignment="Top" Width="120" Text="{Binding model.character.char_exp}"/>
<TextBox x:Name="textbox_name" HorizontalAlignment="Left" Height="22" Margin="61,14,0,0" TextWrapping="NoWrap" VerticalAlignment="Top" Width="120" Text="{Binding character.name}"/>
<TextBox x:Name="textbox_money" HorizontalAlignment="Left" Height="22" Margin="61,44,0,0" TextWrapping="NoWrap" VerticalAlignment="Top" Width="120" Text="{Binding character.money}"/>
<TextBox x:Name="textbox_level" HorizontalAlignment="Left" Height="22" Margin="61,74,0,0" TextWrapping="NoWrap" VerticalAlignment="Top" Width="120" Text="{Binding character.level}"/>
<TextBox x:Name="textbox_exp" HorizontalAlignment="Left" Height="22" Margin="61,104,0,0" TextWrapping="NoWrap" VerticalAlignment="Top" Width="120" Text="{Binding character.exp}"/>
<Button x:Name="button_char_money" Content="Max Money" HorizontalAlignment="Left" Margin="200,44,0,0" VerticalAlignment="Top" Width="88" RenderTransformOrigin="0.065,-0.953" Height="22" Click="button_char_money_Click"/>
<Button x:Name="button_char_exp" Content="Max Exp" HorizontalAlignment="Left" Margin="200,104,0,0" VerticalAlignment="Top" Width="88" RenderTransformOrigin="0.065,-0.953" Height="22" Click="button_char_exp_Click"/>
</Grid>
</TabItem>
<TabItem Header="Monsters">
<Grid Background="#FFE5E5E5"/>
</TabItem>
<TabItem Header="Egg Fragments">
<Grid Background="#FFE5E5E5"/>
</TabItem>
<TabItem Header="Items">
<Grid Background="#FFE5E5E5" Margin="0,0,0,0">
<Button x:Name="button1" Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="100,10,0,0"/>
<DataGrid x:Name="item_table" ItemsSource="{Binding items}" HorizontalAlignment="Left" Margin="10,30,0,0" VerticalAlignment="Top" Height="276" Width="550" CanUserAddRows="False" AutoGenerateColumns="False" >
<DataGrid.Columns>
<DataGridTextColumn CanUserReorder ="False" CanUserResize="False" CanUserSort="False" Width ="100" Foreground="Gray" IsReadOnly="True" Binding="{Binding id}"
Header="ID" />
<DataGridTextColumn CanUserReorder ="False" CanUserResize="False" CanUserSort="False" Width ="100" Foreground="Gray" IsReadOnly="True" Binding="{Binding name}"
Header="Name" />
<DataGridTextColumn CanUserReorder ="False" CanUserResize="False" CanUserSort="False" Width ="*" Binding="{Binding count, Mode=TwoWay}"
Header="Count" />
</DataGrid.Columns>
</DataGrid>
<Button x:Name="button_item_all" Content="All 986x" HorizontalAlignment="Left" Margin="586,30,0,0" VerticalAlignment="Top" Width="108" RenderTransformOrigin="0.065,-0.953" Height="45" Click="button_item_all_Click"/>
<Button x:Name="button_item_existing" Content="Existing 999x" HorizontalAlignment="Left" Margin="586,94,0,0" VerticalAlignment="Top" Width="108" RenderTransformOrigin="0.065,-0.953" Height="45" Click="button_item_existing_Click"/>
</Grid>
</TabItem>
<TabItem Header="Monsters" Margin="0,0,0,0">
<Grid Background="#FFE5E5E5">
<Label x:Name="label_mhp" Content="HP" HorizontalAlignment="Left" Margin="10,85,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.564,2.072"/>
<Label x:Name="label_mat" Content="Atk" HorizontalAlignment="Left" Margin="10,115,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.564,2.072"/>
<Label x:Name="label_mdf" Content="Def" HorizontalAlignment="Left" Margin="10,145,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.564,2.072"/>
<Label x:Name="label_mhiv" Content="IV-HP" HorizontalAlignment="Left" Margin="10,175,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.564,2.072"/>
<Label x:Name="label_mdiv" Content="IV-Atk" HorizontalAlignment="Left" Margin="10,205,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.564,2.072"/>
<Label x:Name="label_maiv" Content="IV-Def" HorizontalAlignment="Left" Margin="10,235,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.564,2.072"/>
<Label x:Name="label_mhpu" Content="PowerUp-HP" HorizontalAlignment="Left" Margin="150,175,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.564,2.072"/>
<Label x:Name="label_mapu" Content="PowerUp-Atk" HorizontalAlignment="Left" Margin="150,205,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.564,2.072"/>
<Label x:Name="label_mdpu" Content="PowerUp-Def" HorizontalAlignment="Left" Margin="150,235,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.564,2.072"/>
<Label x:Name="label_mgen1" Content="Gene1 (Hex)" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="385,85,0,0"/>
<Label x:Name="label_mgen2" Content="Gene2 (Hex)" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="505,85,0,0"/>
<Label x:Name="label_mgen3" Content="Gene3 (Hex)" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="625,85,0,0" RenderTransformOrigin="0.537,0.19"/>
<Label x:Name="label_mgen4" Content="Gene4 (Hex)" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="385,155,0,0"/>
<Label x:Name="label_mgen5" Content="Gene5 (Hex)" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="505,155,0,0" RenderTransformOrigin="0.524,0.439"/>
<Label x:Name="label_mgen6" Content="Gene6 (Hex)" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="625,155,0,0"/>
<Label x:Name="label_mgen7" Content="Gene7 (Hex)" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="385,225,0,0"/>
<Label x:Name="label_mgen8" Content="Gene8 (Hex)" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="505,225,0,0"/>
<Label x:Name="label_mgen9" Content="Gene9 (Hex)" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="625,225,0,0"/>
<TextBox x:Name="textbox_mhp" HorizontalAlignment="Left" Height="23" Margin="60,87,0,0" TextWrapping="Wrap" Text="{Binding Path=cur_monster.hp}" VerticalAlignment="Top" Width="75"/>
<TextBox x:Name="textbox_mat" HorizontalAlignment="Left" Height="23" Margin="60,117,0,0" TextWrapping="Wrap" Text="{Binding Path=cur_monster.atk}" VerticalAlignment="Top" Width="75"/>
<TextBox x:Name="textbox_mdf" HorizontalAlignment="Left" Height="23" Margin="60,147,0,0" TextWrapping="Wrap" Text="{Binding Path=cur_monster.def}" VerticalAlignment="Top" Width="75"/>
<TextBox x:Name="textbox_mhiv" HorizontalAlignment="Left" Height="23" Margin="60,177,0,0" TextWrapping="Wrap" Text="{Binding Path=cur_monster.hiv}" VerticalAlignment="Top" Width="75"/>
<TextBox x:Name="textbox_maiv" HorizontalAlignment="Left" Height="23" Margin="60,207,0,0" TextWrapping="Wrap" Text="{Binding Path=cur_monster.aiv}" VerticalAlignment="Top" Width="75"/>
<TextBox x:Name="textbox_mdiv" HorizontalAlignment="Left" Height="23" Margin="60,237,0,0" TextWrapping="Wrap" Text="{Binding Path=cur_monster.div}" VerticalAlignment="Top" Width="75"/>
<TextBox x:Name="textbox_mhpu" HorizontalAlignment="Left" Height="23" Margin="240,177,0,0" TextWrapping="Wrap" Text="{Binding Path=cur_monster.hpu}" VerticalAlignment="Top" Width="75"/>
<TextBox x:Name="textbox_mapu" HorizontalAlignment="Left" Height="23" Margin="240,207,0,0" TextWrapping="Wrap" Text="{Binding Path=cur_monster.apu}" VerticalAlignment="Top" Width="75"/>
<TextBox x:Name="textbox_mdpu" HorizontalAlignment="Left" Height="23" Margin="240,237,0,0" TextWrapping="Wrap" Text="{Binding Path=cur_monster.dpu}" VerticalAlignment="Top" Width="75"/>
<TextBox x:Name="textbox_gene1" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="{Binding Path=cur_monster.gene1}" VerticalAlignment="Top" Width="80" Margin="385,120,0,0"/>
<TextBox x:Name="textbox_gene2" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="{Binding Path=cur_monster.gene2}" VerticalAlignment="Top" Width="80" Margin="505,120,0,0"/>
<TextBox x:Name="textbox_gene3" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="{Binding Path=cur_monster.gene3}" VerticalAlignment="Top" Width="80" Margin="625,120,0,0"/>
<TextBox x:Name="textbox_gene4" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="{Binding Path=cur_monster.gene4}" VerticalAlignment="Top" Width="80" Margin="385,190,0,0"/>
<TextBox x:Name="textbox_gene5" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="{Binding Path=cur_monster.gene5}" VerticalAlignment="Top" Width="80" Margin="505,190,0,0"/>
<TextBox x:Name="textbox_gene6" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="{Binding Path=cur_monster.gene6}" VerticalAlignment="Top" Width="80" Margin="625,190,0,0"/>
<TextBox x:Name="textbox_gene7" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="{Binding Path=cur_monster.gene7}" VerticalAlignment="Top" Width="80" Margin="385,260,0,0"/>
<TextBox x:Name="textbox_gene8" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="{Binding Path=cur_monster.gene8}" VerticalAlignment="Top" Width="80" Margin="505,260,0,0"/>
<TextBox x:Name="textbox_gene9" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="{Binding Path=cur_monster.gene9}" VerticalAlignment="Top" Width="80" Margin="625,260,0,0"/>
<Label x:Name="label_mlv" Content="Level" HorizontalAlignment="Left" Margin="150,85,0,0" VerticalAlignment="Top" RenderTransformOrigin="-0.263,0.135"/>
<Label x:Name="label_mex" Content="Exp" HorizontalAlignment="Left" Margin="150,115,0,0" VerticalAlignment="Top" RenderTransformOrigin="-0.263,0.135"/>
<Label x:Name="label_spe" Content="Species (Hex)" HorizontalAlignment="Left" Margin="150,145,0,0" VerticalAlignment="Top" RenderTransformOrigin="-0.263,0.135"/>
<TextBox x:Name="textbox_mlv" HorizontalAlignment="Left" Height="24" Margin="240,87,0,0" TextWrapping="Wrap" Text="{Binding Path=cur_monster.level}" VerticalAlignment="Top" Width="75"/>
<TextBox x:Name="textbox_mex" HorizontalAlignment="Left" Height="24" Margin="240,117,0,0" TextWrapping="Wrap" Text="{Binding Path=cur_monster.exp}" VerticalAlignment="Top" Width="75"/>
<TextBox x:Name="textbox_spe" HorizontalAlignment="Left" Height="24" Margin="240,147,0,0" TextWrapping="Wrap" Text="{Binding Path=cur_monster.spe}" VerticalAlignment="Top" Width="75"/>
<Label x:Name="label_mname" Content="Name" HorizontalAlignment="Left" Margin="10,54,0,0" VerticalAlignment="Top"/>
<TextBox x:Name="textbox_mname" HorizontalAlignment="Left" Height="22" Margin="60,58,0,0" TextWrapping="Wrap" Text="{Binding Path=cur_monster.name}" VerticalAlignment="Top" Width="255"/>
<Label x:Name="label_slct" Content="Monster" HorizontalAlignment="Left" Margin="2,10,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.466,0.596"/>
<ComboBox x:Name="combobox_slct" HorizontalAlignment="Left" Margin="60,10,0,0" VerticalAlignment="Top" Width="255" ItemsSource="{Binding Path=monsters}" DisplayMemberPath="full_name" IsReadOnly="True" SelectedValue="{Binding Path=cur_monster}"/>
<Label x:Name="label_m_warn" Content="Warning: The sum of PowerUps should be at most 10." HorizontalAlignment="Left" Margin="12,265,0,0" VerticalAlignment="Top"/>
<Label x:Name="label_m_warn2" Content="The exact IV algorithm is unknown. Edit wisely." HorizontalAlignment="Left" Margin="62,285,0,0" VerticalAlignment="Top"/>
<TextBlock x:Name="textblock_gene101" HorizontalAlignment="Left" Margin="385,16,0,0" TextWrapping="Wrap" Text="MHST Gene 101:&#x0a;0x0001 = Empty Slot&#x0a;0x0002 = No Slot&#x0a;For other genes codes, refer to the gene code mapping." VerticalAlignment="Top"/>
<Button x:Name="button_mexp" Content="Max" HorizontalAlignment="Left" Margin="193,119,0,0" VerticalAlignment="Top" Width="35" Click="button_mexp_Click"/>
</Grid>
</TabItem>
</TabControl>
<Button x:Name="button_save" Content="Save" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="74"/>
<Button x:Name="button_save" Content="Save" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="74" Click="button_save_Click"/>
<Button x:Name="button_load" Content="Load" HorizontalAlignment="Left" Margin="90,10,0,0" VerticalAlignment="Top" Width="74" Click="button_load_click"/>
<DataGrid x:Name="dataGrid" HorizontalAlignment="Left" Height="100" Margin="1046,415,-390,-95.5" VerticalAlignment="Top" Width="100"/>
</Grid>
</Window>

View File

@ -1,20 +1,26 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Forms;
using MessageBox = System.Windows.MessageBox;
namespace MHSEC_G
{
public partial class MainWindow : Window
{
private ViewModel view_model;
private readonly byte[] dummy_data = new byte[Model.SAVE_FILE_SIZE];
private const string Version = "0.1";
public MainWindow()
{
InitializeComponent();
Item.read_item_mappings();
Array.Clear(dummy_data, 0, dummy_data.Length);
this.Title = "MHSEC-G Ver" + Version;
DataContext = new ViewModel(dummy_data);
view_model = new ViewModel(dummy_data);
DataContext = view_model;
}
private void button_load_click(object sender, RoutedEventArgs e)
@ -35,9 +41,58 @@ namespace MHSEC_G
}
else
{
DataContext = new ViewModel(buffer);
view_model = new ViewModel(buffer);
DataContext = view_model;
}
}
}
private void button_char_money_Click(object sender, RoutedEventArgs e)
{
view_model.character.money = Character.LIMIT_MONEY;
}
private void button_char_exp_Click(object sender, RoutedEventArgs e)
{
view_model.character.exp = Character.LIMIT_EXP;
}
private void button_item_all_Click(object sender, RoutedEventArgs e)
{
List<Item> items = view_model.items;
for (uint i = 0; i < items.Count; i++)
{
if (items.ElementAt((int)i).id == 1227)
break;
items.ElementAt((int)i).count = 986;
}
}
private void button_item_existing_Click(object sender, RoutedEventArgs e)
{
List<Item> items = view_model.items;
for (uint i = 0; i < items.Count; i++)
{
if (items.ElementAt((int) i).id == 1227)
break;
if (items.ElementAt((int)i).count != 0)
{
items.ElementAt((int) i).count = 999;
}
}
}
private void button_mexp_Click(object sender, RoutedEventArgs e)
{
view_model.cur_monster.exp = Monster.LIMIT_MONSTER_EXP;
}
private void button_save_Click(object sender, RoutedEventArgs e)
{
File.WriteAllBytes("C:\\Users\\hyper\\Desktop\\mhr_save0.hacked", view_model.model.save_file);
MessageBox.Show("Saved to \"mhr_save0.hacked\"","MHSEC-G",MessageBoxButton.OK, MessageBoxImage.Information);
}
}
}

View File

@ -1,11 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Dynamic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MHSEC_G.Annotations;
namespace MHSEC_G
{
@ -13,44 +8,35 @@ namespace MHSEC_G
{
public const uint SAVE_FILE_SIZE = 483976;
private readonly byte[] save_file;
private readonly byte[] _save_file;
private readonly Character _character;
public Character character
public byte[] save_file
{
get { return _character; }
get { return _save_file; }
}
private uint cur_monster_selection;
private readonly List<Monster> monsters;
private readonly List<Item> items;
private uint cur_egg_fragment_selection;
private readonly List<EggFragment> egg_fragments;
public Model(byte[] save)
{
if (save == null || save.Length != SAVE_FILE_SIZE)
public Model(byte[] save_file)
{
if(save_file.Length != SAVE_FILE_SIZE)
throw new SystemException("Invalid save file size.");
_save_file = save_file;
}
save_file = save;
_character = new Character(save_file);
cur_monster_selection = 0;
monsters = null;
items = null;
cur_egg_fragment_selection = 0;
egg_fragments = null;
}
public static uint byte_to_uint(byte b)
{
return (uint) (b) & 0xFF;
}
public static void write_byte(byte[]arr, uint offset, uint val)
{
if(offset < arr.Length)
arr[offset] = (byte)(val&0xFF);
else
{
throw new SystemException("Buffer overflowed - Offset " + offset);
}
}
public static uint byte_to_uint16_le(byte[] arr, uint offset)
{
if (arr.Length < offset + 2)
@ -105,5 +91,37 @@ namespace MHSEC_G
}
return name.ToString();
}
public static void write_unicode_string(byte[] arr, uint offset, string str, uint length)
{
if (length < str.Length || arr.Length < offset + length)
throw new SystemException("Unicode string write - potential buffer overflow.");
Array.Clear(arr, (int) offset, (int)length*2);
for (uint i = 0; i < str.Length; i ++)
{
write_uint16_le(arr, offset + i*2, str.ElementAt((int) i));
}
return;
}
public static bool parse_hex_string(string val, out uint result)
{
result = 0;
try
{
result = Convert.ToUInt32(val, 16);
}
catch (FormatException)
{
return false;
}
catch (OverflowException)
{
return false;
}
return true;
}
}
}

View File

@ -1,11 +1,453 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows;
using MHSEC_G.Annotations;
namespace MHSEC_G
{
class Monster
public class Monster : INotifyPropertyChanged
{
private const uint OFFSETA_MONSTER = 0xA150;
private const uint SIZE_MONSTER = 0x478;
private const uint OFFSETR_MONSTER_GENE = 0x424;
private const uint SIZE_MONSTER_GENE = 0x4;
private const uint OFFSETR_MONSTER_EXP = 0xE0;
public const uint LIMIT_MONSTER_EXP = 0xFFFFFF;
private const uint OFFSETR_MONSTER_HIV = 0xD8;
private const uint OFFSETR_MONSTER_AIV = 0xD9;
private const uint OFFSETR_MONSTER_DIV = 0xDA;
private const uint OFFSETR_MONSTER_HPU = 0xD4;
private const uint OFFSETR_MONSTER_APU = 0xD5;
private const uint OFFSETR_MONSTER_DPU = 0xD6;
private const uint OFFSETR_MONSTER_LEVEL = 0x5C;
private const uint LIMIT_MONSTER_LEVEL = 99;
private const uint OFFSETR_MONSTER_NAME = 0;
private const uint LIMIT_MONSTER_NAME = 10;
private const uint OFFSETR_MONSTER_SPE = 0x30;
private const uint OFFSETA_MONSTE_END = 0x4786F;
private const uint OFFSETR_MONSTER_ATK = 0x48;
private const uint OFFSETR_MONSTER_HP = 0x46;
private const uint OFFSETR_MONSTER_DEF = 0x4A;
private readonly Model _model;
private readonly uint _offset;
public string spe
{
get { return Model.byte_to_uint(_model.save_file[_offset + OFFSETR_MONSTER_SPE]).ToString("X2"); }
set
{
uint parsed;
if (Model.parse_hex_string(value,out parsed) && parsed <= 0xFF)
{
_model.save_file[_offset + OFFSETR_MONSTER_SPE] = (byte)(parsed & 0xFF);
}
else
{
MessageBox.Show("Species must be at most 0xFF.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(hiv));
}
}
public uint atk
{
get { return Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_ATK); }
set
{
if (value <= 0xFFFF)
{
Model.write_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_ATK, value);
}
else
{
MessageBox.Show("Atk must be at most " + UInt16.MaxValue, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(atk));
}
}
public uint def
{
get { return Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_DEF); }
set
{
if (value <= 0xFFFF)
{
Model.write_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_DEF, value);
}
else
{
MessageBox.Show("Def must be at most " + UInt16.MaxValue, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(def));
}
}
public uint hp
{
get { return Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_HP); }
set
{
if (value <= 0xFFFF)
{
Model.write_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_HP, value);
}
else
{
MessageBox.Show("HP must be at most " + UInt16.MaxValue, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(hp));
}
}
public uint hiv
{
get { return Model.byte_to_uint(_model.save_file[_offset + OFFSETR_MONSTER_HIV]); }
set
{
if (value <= 0xFF)
{
_model.save_file[_offset + OFFSETR_MONSTER_HIV] = (byte) (value & 0xFF);
}
else
{
MessageBox.Show("IV must be at most 255.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(hiv));
}
}
public uint aiv
{
get { return Model.byte_to_uint(_model.save_file[_offset + OFFSETR_MONSTER_AIV]); }
set
{
if (value <= 0xFF)
{
_model.save_file[_offset + OFFSETR_MONSTER_AIV] = (byte)(value & 0xFF);
}
else
{
MessageBox.Show("IV must be at most 255.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(aiv));
}
}
public uint div
{
get { return Model.byte_to_uint(_model.save_file[_offset + OFFSETR_MONSTER_DIV]); }
set
{
if (value <= 0xFF)
{
_model.save_file[_offset + OFFSETR_MONSTER_DIV] = (byte)(value & 0xFF);
}
else
{
MessageBox.Show("IV must be at most 255.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(div));
}
}
public uint hpu
{
get { return Model.byte_to_uint(_model.save_file[_offset + OFFSETR_MONSTER_HPU]); }
set
{
if (value <= 0xFF)
{
_model.save_file[_offset + OFFSETR_MONSTER_HPU] = (byte)(value & 0xFF);
}
else
{
MessageBox.Show("Power up must be at most 255.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(hpu));
}
}
public uint apu
{
get { return Model.byte_to_uint(_model.save_file[_offset + OFFSETR_MONSTER_APU]); }
set
{
if (value <= 0xFF)
{
_model.save_file[_offset + OFFSETR_MONSTER_APU] = (byte)(value & 0xFF);
}
else
{
MessageBox.Show("Power up must be at most 255.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(apu));
}
}
public uint dpu
{
get { return Model.byte_to_uint(_model.save_file[_offset + OFFSETR_MONSTER_DPU]); }
set
{
if (value <= 0xFF)
{
_model.save_file[_offset + OFFSETR_MONSTER_DPU] = (byte)(value & 0xFF);
}
else
{
MessageBox.Show("Power up must be at most 255.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(dpu));
}
}
public string full_name
{
get { return name.Length == 0 ? "" : name + " [Lv." + level + "]"; }
}
public string name
{
get { return Model.read_unicode_string(_model.save_file, _offset + OFFSETR_MONSTER_NAME, LIMIT_MONSTER_NAME); }
set
{
if (value.Length <= 10 && value.Length > 0)
{
Model.write_unicode_string(_model.save_file, _offset + OFFSETR_MONSTER_NAME, value, 10);
}
else
{
MessageBox.Show("Name must be 1-10 characters.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(name));
OnPropertyChanged(nameof(full_name));
}
}
public uint exp
{
get { return Model.byte_to_uint32_le(_model.save_file, _offset + OFFSETR_MONSTER_EXP); }
set
{
if (value <= LIMIT_MONSTER_EXP)
{
Model.write_uint32_le(_model.save_file, _offset + OFFSETR_MONSTER_EXP, value);
}
else
{
MessageBox.Show("Exp must be at most " + LIMIT_MONSTER_EXP, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(exp));
}
}
public uint level
{
get { return Model.byte_to_uint(_model.save_file[_offset + OFFSETR_MONSTER_LEVEL]); }
set
{
if (value <= LIMIT_MONSTER_LEVEL)
{
_model.save_file[_offset + OFFSETR_MONSTER_LEVEL] = (byte)(value & 0xFF);
}
else
{
MessageBox.Show("Level must be at most " + LIMIT_MONSTER_LEVEL, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(level));
OnPropertyChanged(nameof(full_name));
}
}
public string gene1
{
get { return Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_GENE + 0 * SIZE_MONSTER_GENE).ToString("X4"); }
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0xFFFF)
{
Model.write_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_GENE + 0 * SIZE_MONSTER_GENE, parsed);
}
else
{
MessageBox.Show("Malformed gene value - must be 0x0 to 0xFFFF.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(gene2));
}
}
public string gene2
{
get { return Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_GENE + 1 * SIZE_MONSTER_GENE).ToString("X4"); }
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0xFFFF)
{
Model.write_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_GENE + 1*SIZE_MONSTER_GENE, parsed);
}
else
{
MessageBox.Show("Malformed gene value - must be 0x0 to 0xFFFF.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(gene2));
}
}
public string gene3
{
get { return Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_GENE + 2 * SIZE_MONSTER_GENE).ToString("X4"); }
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0xFFFF)
{
Model.write_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_GENE + 2 * SIZE_MONSTER_GENE, parsed);
}
else
{
MessageBox.Show("Malformed gene value - must be 0x0 to 0xFFFF.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(gene3));
}
}
public string gene4
{
get { return Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_GENE + 3 * SIZE_MONSTER_GENE).ToString("X4"); }
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0xFFFF)
{
Model.write_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_GENE + 3 * SIZE_MONSTER_GENE, parsed);
}
else
{
MessageBox.Show("Malformed gene value - must be 0x0 to 0xFFFF.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(gene4));
}
}
public string gene5
{
get { return Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_GENE + 4 * SIZE_MONSTER_GENE).ToString("X4"); }
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0xFFFF)
{
Model.write_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_GENE + 4 * SIZE_MONSTER_GENE, parsed);
}
else
{
MessageBox.Show("Malformed gene value - must be 0x0 to 0xFFFF.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(gene5));
}
}
public string gene6
{
get { return Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_GENE + 5 * SIZE_MONSTER_GENE).ToString("X4"); }
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0xFFFF)
{
Model.write_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_GENE + 5 * SIZE_MONSTER_GENE, parsed);
}
else
{
MessageBox.Show("Malformed gene value - must be 0x0 to 0xFFFF.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(gene6));
}
}
public string gene7
{
get { return Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_GENE + 6 * SIZE_MONSTER_GENE).ToString("X4"); }
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0xFFFF)
{
Model.write_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_GENE + 6 * SIZE_MONSTER_GENE, parsed);
}
else
{
MessageBox.Show("Malformed gene value - must be 0x0 to 0xFFFF.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(gene7));
}
}
public string gene8
{
get { return Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_GENE + 7 * SIZE_MONSTER_GENE).ToString("X4"); }
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0xFFFF)
{
Model.write_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_GENE + 7 * SIZE_MONSTER_GENE, parsed);
}
else
{
MessageBox.Show("Malformed gene value - must be 0x0 to 0xFFFF.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(gene8));
}
}
public string gene9
{
get { return Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_GENE + 8 * SIZE_MONSTER_GENE).ToString("X4"); }
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0xFFFF)
{
Model.write_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_GENE + 8 * SIZE_MONSTER_GENE, parsed);
}
else
{
MessageBox.Show("Malformed gene value - must be 0x0 to 0xFFFF.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(gene9));
}
}
public Monster(uint offset, Model model)
{
_offset = offset;
_model = model;
}
public static List<Monster> read_all_monsters(Model model)
{
byte[] save = model.save_file;
List<Monster> ret = new List<Monster>();
for (uint i = OFFSETA_MONSTER; i < OFFSETA_MONSTE_END; i += SIZE_MONSTER)
{
if (save[i] != 0)
{
byte[] each = new byte[SIZE_MONSTER];
Array.Copy(save, i, each, 0 ,SIZE_MONSTER);
ret.Add(new Monster(i, model));
}
}
if (ret.Count == 0)
{
byte[] dummy = new byte[SIZE_MONSTER];
Array.Clear(dummy, 0, (int)SIZE_MONSTER);
// at least one monster
ret.Add(new Monster(OFFSETA_MONSTER, model));
}
return ret;
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@ -1,24 +1,79 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using MHSEC_G.Annotations;
namespace MHSEC_G
{
public class ViewModel
public class ViewModel : INotifyPropertyChanged
{
private Model _model;
private readonly Model _model;
public Model model
{
get { return _model;}
set { _model = model; }
}
private readonly Character _character;
public ViewModel(byte[] data)
public Character character
{
_model = new Model(data);
get { return _character; }
}
private Monster _cur_monster_selection;
private readonly ObservableCollection<Monster> _monsters;
public Monster cur_monster
{
get { return _cur_monster_selection; }
set { _cur_monster_selection = value; OnPropertyChanged(nameof(cur_monster)); }
}
public ObservableCollection<Monster> monsters
{
get
{
return _monsters;
}
}
private readonly List<Item> _items;
public List<Item> items
{
get { return _items; }
}
private uint cur_egg_fragment_selection;
private readonly List<EggFragment> egg_fragments;
public ViewModel(byte[] save)
{
if (save == null || save.Length != Model.SAVE_FILE_SIZE)
{
throw new SystemException("Invalid save file size.");
}
_model = new Model(save);
_character = new Character(_model);
_items = Item.read_all_items(_model);
_monsters = new ObservableCollection<Monster>(Monster.read_all_monsters(_model));
_cur_monster_selection = _monsters.ElementAt(0);
cur_egg_fragment_selection = 0;
egg_fragments = null;
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

BIN
MHSEC-G/MHSEC-G/idmap.txt Normal file

Binary file not shown.