342 lines
12 KiB
C#
342 lines
12 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Dynamic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Windows;
|
|
using MHSEC_G.Annotations;
|
|
|
|
namespace MHSEC_G
|
|
{
|
|
public class Monster : INotifyPropertyChanged
|
|
{
|
|
public const uint LIMIT_MONSTER_EXP = 0xFFFFFF;
|
|
public const uint SIZE_MONSTER = 0x478;
|
|
private const uint OFFSETA_MONSTER = 0xA150;
|
|
private const uint OFFSETR_MONSTER_GENE = 0x424;
|
|
private const uint SIZE_MONSTER_GENE = 0x4;
|
|
private const uint OFFSETR_MONSTER_EXP = 0xE0;
|
|
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_SKILL = 0x38;
|
|
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 uint offset => _offset;
|
|
public uint box => (_offset - OFFSETA_MONSTER) / SIZE_MONSTER / 18 + 1;
|
|
public uint slot => (_offset - OFFSETA_MONSTER) / SIZE_MONSTER % 18 + 1;
|
|
|
|
private readonly Genes _genes;
|
|
public Genes genes => _genes;
|
|
|
|
public string spe
|
|
{
|
|
get => 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(spe));
|
|
}
|
|
}
|
|
|
|
public uint atk
|
|
{
|
|
get => 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 => 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 => 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 => 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 => 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 => 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 => 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 => 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 => 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 name
|
|
{
|
|
get => 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,
|
|
LIMIT_MONSTER_NAME);
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Name must be 1-10 characters.", "Error", MessageBoxButton.OK,
|
|
MessageBoxImage.Error);
|
|
}
|
|
OnPropertyChanged(nameof(name));
|
|
}
|
|
}
|
|
|
|
public uint exp
|
|
{
|
|
get => 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 => 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));
|
|
}
|
|
}
|
|
|
|
public string skill
|
|
{
|
|
get => Model.byte_to_uint16_le(_model.save_file, offset + OFFSETR_MONSTER_SKILL).ToString("X4");
|
|
set
|
|
{
|
|
uint parsed;
|
|
if (Model.parse_hex_string(value, out parsed))
|
|
{
|
|
Model.write_uint16_le(_model.save_file, offset + OFFSETR_MONSTER_SKILL, parsed);
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Malformed skill value - must be 0x0 to 0xFFFF.", "Error", MessageBoxButton.OK,
|
|
MessageBoxImage.Error);
|
|
}
|
|
|
|
OnPropertyChanged(nameof(skill));
|
|
}
|
|
}
|
|
|
|
|
|
public Monster(uint offset, Model model)
|
|
{
|
|
_offset = offset;
|
|
_model = model;
|
|
_genes = new Genes(model, offset + OFFSETR_MONSTER_GENE, SIZE_MONSTER_GENE);
|
|
}
|
|
|
|
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)
|
|
{
|
|
ret.Add(new Monster(i, model));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
public byte[] getByteArray()
|
|
{
|
|
byte[] ret = new byte[SIZE_MONSTER];
|
|
Array.Copy(_model.save_file, _offset, ret, 0, SIZE_MONSTER);
|
|
return ret;
|
|
}
|
|
|
|
public void setByteArray(byte[] ret)
|
|
{
|
|
Array.Copy(ret, 0, _model.save_file, _offset, SIZE_MONSTER);
|
|
OnPropertyChanged(null);
|
|
}
|
|
|
|
|
|
public event PropertyChangedEventHandler PropertyChanged;
|
|
|
|
[NotifyPropertyChangedInvocator]
|
|
protected virtual void OnPropertyChanged(string propertyName)
|
|
{
|
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
}
|
|
}
|
|
}
|