code:
#pragma once
#include "Database/Log.hpp"
#include <orei18n.hpp>

#include <optional>
#include <string>

#define MAGIC_ENUM_RANGE_MIN (-4096)
#define MAGIC_ENUM_RANGE_MAX (4096)
#include <magic_enum/magic_enum.hpp>

/* DO NOT MODIFY ENUM NAMES
 * They may not seem like they make sense,
 * but they have a purpose.
 * magic_enum is used to get the value of the enum's name
 * We have some special encoding to add in special characters
 *
 * The currently available encoding is the follow:
 * po_ -> (
 * _pc -> )
 * bo_ -> [
 * _bc -> ]
 * _pe_ -> .
 * _del_ -> useful placeholder for name collisions inserts a null and truncats the strings
 * _deg -> °
 * _da_ -> -=
 * _daa_ -> -
 * _pl_ -> +=
 * _plu_ -> +
 *
 * After the special characters have been decoded and inserted any remaining
 * underscores are replaced with spaces
 */

/* May be something else so this is prelim */
enum class ParameterSource {
  trENUM("Max HP", Max_HP),
  trENUM("Max MP", Max_MP),
  trENUM("Attack", Attack),
  trENUM("Defense", Defense),
  trENUM("M.Attack", trENUM("MAttack", M_pe_Attack)),
  trENUM("M.Defense", trENUM("MDefense", M_pe_Defense)),
  trENUM("Agility", Agility),
  trENUM("Luck", Luck),
};

enum class DebuffSource {
  trENUM("Max HP", Max_HP),
  trENUM("Max MP", Max_MP),
  trENUM("Attack", Attack),
  trENUM("Defense", Defense),
  trENUM("M.Attack", trENUM("M Attack", M_pe_Attack)),
  trENUM("M.Defense", trENUM("M Defense", M_pe_Defense)),
  trENUM("Agility", Agility),
  trENUM("Luck", Luck),
};

enum class EXParameterSource {
  trENUM("Hit Rate", Hit_Rate),
  trENUM("Evasion Rate", Evasion_Rate),
  trENUM("Critical Rate", Critical_Rate),
  trENUM("Critical Evasion", Critical_Evasion),
  trENUM("Magic Evasion", Magic_Evasion),
  trENUM("Magic Reflection", Magic_Reflection),
  trENUM("Counter Attack", Counter_Attack),
  trENUM("HP Regeneration", HP_Regeneration),
  trENUM("MP Regeneration", MP_Regeneration),
  trENUM("TP Regeneration", TP_Regeneration),
};

enum class SPParameterSource {
  trENUM("Target Rate", Target_Rate),
  trENUM("Guard Effect", Guard_Effect),
  trENUM("Recovery Effect", Recovery_Effect),
  trENUM("Pharmacology", Pharmacology),
  trENUM("MP Cost Rate", MP_Cost_Rate),
  trENUM("TP Charge Rate", TP_Charge_Rate),
  trENUM("Physical Damage", Physical_Damage),
  trENUM("Magical Damage", Magical_Damage),
  trENUM("Floor Damage", Floor_Damage),
  trENUM("Experience", Experience),
};

enum class SlotType {
  trENUM("Normal", Normal),
  trENUM("Dual Wield", Dual_Wield),
};

enum class SpecialFlag {
  trENUM("Auto Battle", Auto_Battle),
  trENUM("Guard", Guard),
  trENUM("Substitute", Substitute),
  trENUM("Preserve TP", Preserve_TP),
};

enum class CollapseEffect {
  trENUM("Normal", Normal),
  trENUM("Boss", Boss),
  trENUM("Instant", Instant),
  trENUM("No Disappear", No_Disappear),
};

enum class PartyAbility {
  trENUM("Encounter Half", Encounter_Half),
  trENUM("Encounter None", Encounter_None),
  trENUM("Cancel Surprise", Cancel_Surprise),
  trENUM("Raise Preemptive", Raise_Preemptive),
  trENUM("Gold Double", Gold_Double),
  trENUM("Drop Item Double", Drop_Item_Double),
};
enum class EffectCode {
  trENUM("Recover HP", Recover_HP) = 11,
  trENUM("Recover MP", Recover_MP) = 12,
  trENUM("Gain TP", Gain_TP) = 13,
  trENUM("Add State", Add_State) = 21,
  trENUM("Remove State", Remove_State) = 22,
  trENUM("Add Buff", Add_Buff) = 31,
  trENUM("Add Debuff", Add_Debuff) = 32,
  trENUM("Remove Buff", Remove_Buff) = 33,
  trENUM("Remove Debuff", Remove_Debuff) = 34,
  trENUM("Special Effect", Special_Effect) = 41,
  trENUM("Grow", Grow) = 42,
  trENUM("Learn Skill", Learn_Skill) = 43,
  trENUM("Common Event", Common_Event) = 44,
};

enum class TraitCode {
  trENUM("Element Rate", Element_Rate) = 11,
  trENUM("Debuff Rate", Debuff_Rate) = 12,
  trENUM("State Rate", State_Rate) = 13,
  trENUM("State Resist", State_Resist) = 14,
  trENUM("Parameter", Parameter) = 21,
  trENUM("Ex-Parameter", trENUM("ExParameter", Ex_daa_Parameter)) = 22,
  trENUM("Sp-Parameter", trENUM("SpParameter", Sp_daa_Parameter)) = 23,
  trENUM("Attack Element", Attack_Element) = 31,
  trENUM("Attack State", Attack_State) = 32,
  trENUM("Attack Speed", Attack_Speed) = 33,
  trENUM("Attack Times +", trENUM("Attack Times ", Attack_Times__plu_)) = 34,
  trENUM("Add Skill Type", Add_Skill_Type) = 41,
  trENUM("Seal Skill Type", Seal_Skill_Type) = 42,
  trENUM("Add Skill", Add_Skill) = 43,
  trENUM("Seal Skill", Seal_Skill) = 44,
  trENUM("Equip Weapon", Equip_Weapon) = 51,
  trENUM("Equip Armor", Equip_Armor) = 52,
  trENUM("Lock Equip", Lock_Equip) = 53,
  trENUM("Seal Equip", Seal_Equip) = 54,
  trENUM("Slot Type", Slot_Type) = 55,
  trENUM("Action Times +", trENUM("Action Times ", Action_Times__plu_)) = 61,
  trENUM("Special Flag", Special_Flag) = 62,
  trENUM("Collapse Effect", Collapse_Effect) = 63,
  trENUM("Party Ability", Party_Ability) = 64,
};

enum class Direction {
  trENUM("Retain", Retain) = 0,
  trENUM("Down", Down) = 2,
  trENUM("Left", Left) = 4,
  trENUM("Right", Right) = 6,
  trENUM("Up", Up) = 8,
};

enum class Button {
  trENUM("OK", OK),
  trENUM("Cancel", Cancel),
  trENUM("Shift", Shift),
  trENUM("Down", Down),
  trENUM("Left", Left),
  trENUM("Right", Right),
  trENUM("Up", Up),
  trENUM("Pageup", Pageup),
  trENUM("Pagedown", Pagedown),
};

enum class HitType {
  trENUM("Certain Hit", Certain_Hit),
  trENUM("Physical Attack", Physical_Attack),
  trENUM("Magical Attack", Magical_Attack),
};

enum class Occasion {
  trENUM("Always", Always),
  trENUM("BattleScreen", BattleScreen),
  trENUM("MenuScreen", MenuScreen),
  trENUM("Never", Never),
};

enum class Scope {
  trENUM("None", None),
  trENUM("1 Enemy", _1_Enemy),
  trENUM("All Enemies", All_Enemies),
  trENUM("1 Random Enemy", _1_Random_Enemy),
  trENUM("2 Random Enemies", _2_Random_Enemies),
  trENUM("3 Random Enemies", _3_Random_Enemies),
  trENUM("4 Random Enemies", _4_Random_Enemies),
  trENUM("1 Ally", _1_Ally),
  trENUM("All Allies", All_Allies),
  trENUM("1 Ally (Dead)", trENUM("1 Ally Dead", _1_Ally_po_Dead_pc)),
  trENUM("All Allies (Dead)", trENUM("All Allies Dead", All_Allies_po_Dead_pc)),
  trENUM("The User", The_User),
};

enum class AutoRemovalTiming {
  trENUM("None", None),
  trENUM("Action End", Action_End),
  trENUM("Turn End", Turn_End),
};

enum class ItemType {
  trENUM("Regular Item", Regular_Item) = 1,
  trENUM("Key Item", Key_Item),
  trENUM("Hidden Item A", Hidden_Item_A),
  trENUM("Hidden Item B", Hidden_Item_B),
};

enum class Mirror {
  trENUM("No", No),
  trENUM("Yes", Yes),
};

enum class Blend {
  trENUM("Normal", Normal),
  trENUM("Additive", Additive),
  trENUM("Multiply", Multiply),
  trENUM("Screen", Screen),
};

enum class FlashScope {
  trENUM("None", None),
  trENUM("Target", Target),
  trENUM("Screen", Screen),
  trENUM("Hide Target", Hide_Target),
};

enum class SEType {
  BGM,
  BGS,
  SE,
  ME,
};

enum class Position {
  trENUM("Head", Head),
  trENUM("Center", Center),
  trENUM("Feet", Feet),
  trENUM("Screen", Screen),
};

enum class DamageType {
  trENUM("None", None),
  trENUM("HP Damage", HP_Damage),
  trENUM("MP Damage", MP_Damage),
  trENUM("HP Recover", HP_Recover),
  trENUM("MP Recover", MP_Recover),
  trENUM("HP Drain", HP_Drain),
  trENUM("MP Drain", MP_Drain),
};

enum class TimerComparisonType {
  trENUM("≥", trENUM("Greater than or Equal to", _gteq__del_Greater_than_or_Equal_to)) = 0,
  trENUM("≤", trENUM("Less than or Equal to", _lteq__del_Less_than_or_Equal_to)) = 1,
};

enum class ConditionType {
  trENUM("Switch", Switch),
  trENUM("Variable", Variable),
  trENUM("Self Switch", Self_Switch),
  trENUM("Timer", Timer),
  trENUM("Actor", Actor),
  trENUM("Enemy", Enemy),
  trENUM("Character", Character),
  trENUM("Gold", Gold),
  trENUM("Item", Item),
  trENUM("Weapon", Weapon),
  trENUM("Armor", Armor),
  trENUM("Button", Button),
  trENUM("Script", Script),
  trENUM("Vehicle", Vehicle),
};

enum class ActorConditionType {
  trENUM("In The Party", In_The_Party),
  trENUM("Name", Name),
  trENUM("Class", Class),
  trENUM("Skill", Skill),
  trENUM("Weapon", Weapon),
  trENUM("Armor", Armor),
  trENUM("State", State),
};

enum class EnemyConditionType {
  trENUM("Appeared", Appeared),
  trENUM("State", State),
};

enum class VariableComparisonSource {
  trENUM("Constant", Constant),
  trENUM("Variable", Variable),
};

enum class ActorComparisonSource {
  trENUM("Fixed", Fixed),
  trENUM("Variable", Variable),
};

enum class SubjectComparisonSource {
  trENUM("Enemy", Enemy),
  trENUM("Actor", Actor),
};

enum class VariableComparisonType {
  trENUM("=", trENUM("Equal To", _set__del_Equal_To)) = 0,
  trENUM("≥", trENUM("Greater than or Equal to", _gteq__del_Greater_than_or_Equal_to)) = 1,
  trENUM("≤", trENUM("Less than or Equal to", _lteq__del_Less_than_or_Equal_to)) = 2,
  trENUM(">", trENUM("Greater than", _gt__del_Greater_than)) = 3,
  trENUM("<", trENUM("Less than", _lt__del_Less_than)) = 4,
  trENUM("!=", trENUM("Not Equal to", _not__set__del_Not_Equal_to)) = 5,
};

enum class GoldComparisonType {
  trENUM("≥", trENUM("Greater than or Equal to", _gteq__del_Greater_than_or_Equal_to)) = 0,
  trENUM("≤", trENUM("Less than or Equal to", _lteq__del_Less_than_or_Equal_to)) = 1,
  trENUM("<", trENUM("Less than", _lt__del_Less_than)) = 2,
};

enum class ValueControl {
  trENUM("ON", ON),
  trENUM("OFF", OFF),
};

enum class VariableControlOperation {
  trENUM("=", trENUM("Set", _set__del_Set)),
  trENUM("+=", trENUM("Add", _pl__del_Add)),
  trENUM("-=", trENUM("Sub", _da__del_Sub)),
  trENUM("*=", trENUM("Mul", _mul__del_Mul)),
  trENUM("/=", trENUM("Div", _div__del_Div)),
  trENUM("%=", trENUM("Mod", _mod__del_Mod)),
};

enum class VariableControlOperand {
  trENUM("Constant", Constant),
  trENUM("Variable", Variable),
  trENUM("Random", Random),
  trENUM("Game Data", Game_Data),
  trENUM("Script", Script),
};

enum class GameDataType {
  trENUM("Item", Item),
  trENUM("Weapon", Weapon),
  trENUM("Armor", Armor),
  trENUM("Actor", Actor),
  trENUM("Enemy", Enemy),
  trENUM("Character", Character),
  trENUM("Party", Party),
  trENUM("Other", Other),
};

enum class ActorDataSource {
  trENUM("Level", Level),
  trENUM("EXP", EXP),
  trENUM("HP", HP),
  trENUM("MP", MP),
  trENUM("Max HP", Max_HP),
  trENUM("Max MP", Max_MP),
  trENUM("Attack", Attack),
  trENUM("Defense", Defense),
  trENUM("M.Attack", trENUM("MAttack", M_pe_Attack)),
  trENUM("M.Defense", trENUM("MDefense", M_pe_Defense)),
  trENUM("Agility", Agility),
  trENUM("Luck", Luck),
};

enum class EnemyDataSource {
  trENUM("HP", HP),
  trENUM("MP", MP),
  trENUM("Max HP", Max_HP),
  trENUM("Max MP", Max_MP),
  trENUM("Attack", Attack),
  trENUM("Defense", Defense),
  trENUM("M.Attack", trENUM("MAttack", M_pe_Attack)),
  trENUM("M.Defense", trENUM("MDefense", M_pe_Defense)),
  trENUM("Agility", Agility),
  trENUM("Luck", Luck),
};

enum class CharacterDataSource {
  trENUM("Map X", Map_X),
  trENUM("Map Y", Map_Y),
  trENUM("Direction", Direction),
  trENUM("Screen X", Screen_X),
  trENUM("Screen Y", Screen_Y),
};

enum class OtherDataSource {
  trENUM("Map ID", Map_ID),
  trENUM("Party Members", Party_Members),
  trENUM("Gold", Gold),
  trENUM("Steps", Steps),
  trENUM("Play Time", Play_Time),
  trENUM("Timer", Timer),
  trENUM("Save Count", Save_Count),
  trENUM("Battle Count", Battle_Count),
  trENUM("Win Count", Win_Count),
  trENUM("Escape Count", Escape_Count),
};

enum class SpecialEffectSource {
  trENUM("Escape", Escape),
};

enum class PartyMemberOperation {
  trENUM("+", trENUM("Add", _plu__del_Add)),
  trENUM("-", trENUM("Remove", _daa__del_Remove)),
};

enum class ColorTone {
  trENUM("Red", Red),
  trENUM("Green", Green),
  trENUM("Blue", Blue),
  trENUM("Gray", Gray),
};

enum class SkillOperation {
  trENUM("+", trENUM("Learn", _plu__del_Learn)),
  trENUM("-", trENUM("Forget", _daa__del_Forget)),
};

enum class AccessMode {
  trENUM("Disable", Disable),
  trENUM("Enable", Enable),
};

enum class TransferMode {
  trENUM("Direct", Direct),
  trENUM("Variable Designation", Variable_Designation),
  trENUM("Exchange With Another Event", Exchange_With_Another_Event),
};

enum class Fade {
  trENUM("Black", Black),
  trENUM("White", White),
  trENUM("None", None),
};

enum class BalloonIcon {
  trENUM("Exclamation", Exclamation) = 1,
  trENUM("Question", Question),
  trENUM("Music Note", Music_Note),
  trENUM("Heart", Heart),
  trENUM("Anger", Anger),
  trENUM("Sweat", Sweat),
  trENUM("Cobweb", Cobweb),
  trENUM("Silence", Silence),
  trENUM("Light Bulb", Light_Bulb),
  trENUM("Zzz", Zzz),
  trENUM("User-defined 1", trENUM("Userdefined 1", User_daa_defined_1)),
  trENUM("User-defined 2", trENUM("Userdefined 2", User_daa_defined_2)),
  trENUM("User-defined 3", trENUM("Userdefined 3", User_daa_defined_3)),
  trENUM("User-defined 4", trENUM("Userdefined 4", User_daa_defined_4)),
  trENUM("User-defined 5", trENUM("Userdefined 5", User_daa_defined_5)),
};

enum class PictureOrigin {
  trENUM("Upper Left", Upper_Left),
  trENUM("Center", Center),
};

enum class WeatherEffect {
  trENUM("None", None),
  trENUM("Rain", Rain),
  trENUM("Storm", Storm),
  trENUM("Snow", Snow),
};

enum class PictureDesignationSource {
  trENUM("Direct designation", Direct_designation),
  trENUM("Designation with variables", Designation_with_variables),
};

enum class EventCode : int {
  Event_Dummy = 0,
  trENUM("Move Down", Move_Down) = 1,
  trENUM("Move Left", Move_Left) = 2,
  trENUM("Move Right", Move_Right) = 3,
  trENUM("Move Up", Move_Up) = 4,
  trENUM("Move Lower Left", Move_Lower_Left) = 5,
  trENUM("Move Lower Right", Move_Lower_Right) = 6,
  trENUM("Move Upper Left", Move_Upper_Left) = 7,
  trENUM("Move Upper Right", Move_Upper_Right) = 8,
  trENUM("Move at Random", Move_at_Random) = 9,
  trENUM("Move toward Player", Move_toward_Player) = 10,
  trENUM("Move away from Player", Move_away_from_Player) = 11,
  trENUM("1 Step Forward", _1_Step_Forward) = 12,
  trENUM("1 Step Backward", _1_Step_Backward) = 13,
  trENUM("Jump", Jump) = 14,
  trENUM("Wait", Wait_del_Movement) = 15,
  trENUM("Turn Down", Turn_Down) = 16,
  trENUM("Turn Left", Turn_Left) = 17,
  trENUM("Turn Right", Turn_Right) = 18,
  trENUM("Turn Up", Turn_Up) = 19,
  trENUM("Turn 90° Right", trENUM("Turn 90 Right", Turn_90_deg_Right)) = 20,
  trENUM("Turn 90° Left", trENUM("Turn 90 Left", Turn_90_deg_Left)) = 21,
  trENUM("Turn 180°", trENUM("Turn 180", Turn_180_deg)) = 22,
  trENUM("Turn 90° Left or Right", trENUM("Turn 90 Left or Right", Turn_90_deg_Left_or_Right)) = 23,
  trENUM("Turn at Random", Turn_at_Random) = 24,
  trENUM("Turn toward Player", Turn_toward_Player) = 25,
  trENUM("Turn away from Player", Turn_away_from_Player) = 26,
  trENUM("Switch ON", Switch_ON) = 27,
  trENUM("Switch OFF", Switch_OFF) = 28,
  trENUM("Speed", Speed) = 29,
  trENUM("Frequency", Frequency) = 30,
  trENUM("Walking Animation ON", Walking_Animation_ON) = 31,
  trENUM("Walking Animation OFF", Walking_Animation_OFF) = 32,
  trENUM("Stepping Animation ON", Stepping_Animation_ON) = 33,
  trENUM("Stepping Animation OFF", Stepping_Animation_OFF) = 34,
  trENUM("Direction Fix ON", Direction_Fix_ON) = 35,
  trENUM("Direction Fix OFF", Direction_Fix_OFF) = 36,
  trENUM("Through ON", Through_ON) = 37,
  trENUM("Through OFF", Through_OFF) = 38,
  trENUM("Transparent ON", Transparent_ON) = 39,
  trENUM("Transparent OFF", Transparent_OFF) = 40,
  trENUM("Change Image", Change_Image) = 41,
  trENUM("Change Opacity", Change_Opacity) = 42,
  trENUM("Change Blend Mode", Change_Blend_Mode) = 43,
  trENUM("Play SE", Play_SE_del_Movement) = 44,
  trENUM("Script", Script_del_Movement) = 45,
  trENUM("Show Text", Show_Text) = 101,
  trENUM("Show Choices", Show_Choices) = 102,
  trENUM("Input Number", Input_Number) = 103,
  trENUM("Select Item", Select_Item) = 104,
  trENUM("Show Scrolling Text", Show_Scrolling_Text) = 105,
  trENUM("Comment", Comment) = 108,
  trENUM("Conditional Branch", Conditional_Branch) = 111,
  trENUM("Loop", Loop) = 112,
  trENUM("Break Loop", Break_Loop) = 113,
  trENUM("Exit Event Processing", Exit_Event_Processing) = 115,
  trENUM("Common Event", Common_Event) = 117,
  trENUM("Label", Label) = 118,
  trENUM("Jump To Label", Jump_To_Label) = 119,
  trENUM("Control Switches", Control_Switches) = 121,
  trENUM("Control Variables", Control_Variables) = 122,
  trENUM("Control Self Switch", Control_Self_Switch) = 123,
  trENUM("Control Timer", Control_Timer) = 124,
  trENUM("Change Gold", Change_Gold) = 125,
  trENUM("Change Items", Change_Items) = 126,
  trENUM("Change Weapons", Change_Weapons) = 127,
  trENUM("Change Armors", Change_Armors) = 128,
  trENUM("Change Party Member", Change_Party_Member) = 129,
  trENUM("Change Battle BGM", Change_Battle_BGM) = 132,
  trENUM("Change Victory ME", Change_Victory_ME) = 133,
  trENUM("Change Save Access", Change_Save_Access) = 134,
  trENUM("Change Menu Access", Change_Menu_Access) = 135,
  trENUM("Change Encounter", Change_Encounter) = 136,
  trENUM("Change Formation Access", Change_Formation_Access) = 137,
  trENUM("Change Window Color", Change_Window_Color) = 138,
  trENUM("Change Defeat ME", Change_Defeat_ME) = 139,
  trENUM("Change Vehicle BGM", Change_Vehicle_BGM) = 140,
  trENUM("Transfer Player", Transfer_Player) = 201,
  trENUM("Set Vehicle Location", Set_Vehicle_Location) = 202,
  trENUM("Set Event Location", Set_Event_Location) = 203,
  trENUM("Scroll Map", Scroll_Map) = 204,
  trENUM("Set Movement Route", Set_Movement_Route) = 205,
  trENUM("Get on/off Vehicle", Get_on_fwsl_off_Vehicle) = 206,
  trENUM("Change Transparency", Change_Transparency) = 211,
  trENUM("Show Animation", Show_Animation) = 212,
  trENUM("Show Balloon Icon", Show_Balloon_Icon) = 213,
  trENUM("Erase Event", Erase_Event) = 214,
  trENUM("Change Player Followers", Change_Player_Followers) = 216,
  trENUM("Gather Followers", Gather_Followers) = 217,
  trENUM("Fadeout Screen", Fadeout_Screen) = 221,
  trENUM("Fadein Screen", Fadein_Screen) = 222,
  trENUM("Tint Screen", Tint_Screen) = 223,
  trENUM("Flash Screen", Flash_Screen) = 224,
  trENUM("Shake Screen", Shake_Screen) = 225,
  trENUM("Wait", Wait) = 230,
  trENUM("Show Picture", Show_Picture) = 231,
  trENUM("Move Picture", Move_Picture) = 232,
  trENUM("Rotate Picture", Rotate_Picture) = 233,
  trENUM("Tint Picture", Tint_Picture) = 234,
  trENUM("Erase Picture", Erase_Picture) = 235,
  trENUM("Set Weather Effect", Set_Weather_Effect) = 236,
  trENUM("Play BGM", Play_BGM) = 241,
  trENUM("Fadeout BGM", Fadeout_BGM) = 242,
  trENUM("Save BGM", Save_BGM) = 243,
  trENUM("Resume BGM", Resume_BGM) = 244,
  trENUM("Play BGS", Play_BGS) = 245,
  trENUM("Fadeout BGS", Fadeout_BGS) = 246,
  trENUM("Play ME", Play_ME) = 249,
  trENUM("Play SE", Play_SE) = 250,
  trENUM("Stop SE", Stop_SE) = 251,
  trENUM("Play Movie", Play_Movie) = 261,
  trENUM("Change Map Display Name", Change_Map_Display_Name) = 281,
  trENUM("Change Tileset", Change_Tileset) = 282,
  trENUM("Change Battle Back", Change_Battle_Back) = 283,
  trENUM("Change Parallax", Change_Parallax) = 284,
  trENUM("Get Location Info", Get_Location_Info) = 285,
  trENUM("Battle Processing", Battle_Processing) = 301,
  trENUM("Shop Processing", Shop_Processing) = 302,
  trENUM("Name Input Processing", Name_Input_Processing) = 303,
  trENUM("Change HP", Change_HP) = 311,
  trENUM("Change MP", Change_MP) = 312,
  trENUM("Change State", Change_State) = 313,
  trENUM("Recover All", Recover_All) = 314,
  trENUM("Change EXP", Change_EXP) = 315,
  trENUM("Change Level", Change_Level) = 316,
  trENUM("Change Parameter", Change_Parameter) = 317,
  trENUM("Change Skill", Change_Skill) = 318,
  trENUM("Change Equipment", Change_Equipment) = 319,
  trENUM("Change Name", Change_Name) = 320,
  trENUM("Change Class", Change_Class) = 321,
  trENUM("Change Actor Images", Change_Actor_Images) = 322,
  trENUM("Change Vehicle Image", Change_Vehicle_Image) = 323,
  trENUM("Change Nickname", Change_Nickname) = 324,
  trENUM("Change Profile", Change_Profile) = 325,
  trENUM("Change TP", Change_TP) = 326,
  trENUM("Change Enemy HP", Change_Enemy_HP) = 331,
  trENUM("Change Enemy MP", Change_Enemy_MP) = 332,
  trENUM("Change Enemy State", Change_Enemy_State) = 333,
  trENUM("Enemy Recover All", Enemy_Recover_All) = 334,
  trENUM("Enemy Appear", Enemy_Appear) = 335,
  trENUM("Enemy Transform", Enemy_Transform) = 336,
  trENUM("Show Battle Animation", Show_Battle_Animation) = 337,
  trENUM("Force Action", Force_Action) = 339,
  trENUM("Abort Battle", Abort_Battle) = 340,
  trENUM("Change Enemy TP", Change_Enemy_TP) = 342,
  trENUM("Open Menu Screen", Open_Menu_Screen) = 351,
  trENUM("Open Save Screen", Open_Save_Screen) = 352,
  trENUM("Game Over", Game_Over) = 353,
  trENUM("Return To Title Screen", Return_To_Title_Screen) = 354,
  trENUM("Script", Script) = 355,
  trENUM("Plugin Command", Plugin_Command_del_MV) = 356,
  trENUM("Plugin Command", Plugin_Command_del_MZ) = 357,
  trENUM("Next Text", Next_Text) = 401,
  trENUM("When Selected", When_Selected) = 402,
  trENUM("When Cancel", When_Cancel) = 403,
  trENUM("End", End_del_ShowChoices) = 404,
  trENUM("Next Scrolling Text", Next_Scrolling_Text) = 405,
  trENUM("Next Comment", Next_Comment) = 408,
  trENUM("Else", Else) = 411,
  trENUM("End", End) = 412,
  trENUM("Repeat Above", Repeat_Above) = 413,
  trENUM("Movement Route Step", Movement_Route_Step) = 505,
  trENUM("If Win", If_Win) = 601,
  trENUM("If Escape", If_Escape) = 602,
  trENUM("If Lose", If_Lose) = 603,
  trENUM("End", End_del_Battle_Processing) = 604,
  trENUM("Shop Processing Good", Shop_Processing_Good) = 605,
  trENUM("Next Script", Next_Script) = 655,
  trENUM("Next PluginMZ Command", Next_PluginMZ_Command) = 657,
};

enum class QuantityChangeOp {
  trENUM("+", trENUM("Increase", _plu__del_Increase)),
  trENUM("-", trENUM("Decrease", _daa__del_Decrease)),
};

enum class QuantityChangeSource {
  trENUM("Constant", Constant),
  trENUM("Variable", Variable),
};

enum class ShopType {
  trENUM("Item", Item),
  trENUM("Weapon", Weapon),
  trENUM("Armor", Armor),
};

enum class PriceType {
  trENUM("Standard", Standard),
  trENUM("Specific", Specific),
};

enum class ActionCondition {
  trENUM("Always", Always),
  trENUM("Turn", Turn),
  trENUM("HP", HP),
  trENUM("MP", MP),
  trENUM("State", State),
  trENUM("Party Level", Party_Level),
  trENUM("Switch", Switch),
};

enum class StateOverlay {
  trENUM("None", None),
  trENUM("Poison", Poison),
  trENUM("Blind", Blind),
  trENUM("Silence", Silence),
  trENUM("Rage", Rage),
  trENUM("Confusion", Confusion),
  trENUM("Fascination", Fascination),
  trENUM("Sleep", Sleep),
  trENUM("Paralyze", Paralyze),
  trENUM("Curse", Curse),
  trENUM("Fear", Fear),
};

enum class StateMotion {
  trENUM("Normal", Normal),
  trENUM("Abnormal", Abnormal),
  trENUM("Sleep", Sleep),
  trENUM("Dead", Dead),
};

enum class StateRestriction {
  trENUM("None", None),
  trENUM("Attack an Enemy", Attack_an_Enemy),
  trENUM("Attack anyone", Attack_anyone),
  trENUM("Attack an ally", Attack_an_ally),
  trENUM("Cannot move", Cannot_move),
};

enum class ScrollType {
  trENUM("No Loop", No_Loop),
  trENUM("Loop Vertically", Loop_Vertically),
  trENUM("Loop Horizontally", Loop_Horizontally),
  trENUM("Loop Both", Loop_Both),
};

enum class TextBackground {
  trENUM("Window", Window),
  trENUM("Dim", Dim),
  trENUM("Transparent", Transparent),
};

enum class TextWindowPosition {
  trENUM("Top", Top),
  trENUM("Middle", Middle),
  trENUM("Bottom", Bottom),
};

enum class ChoiceWindowPosition {
  trENUM("Left", Left),
  trENUM("Middle", Middle),
  trENUM("Right", Right),
};

enum class MovementSpeed {
  trENUM("x8 Slower", x8_Slower) = 1,
  trENUM("x4 Slower", x4_Slower),
  trENUM("x2 Slower", x2_Slower),
  trENUM("Normal", Normal),
  trENUM("x2 Faster", x2_Faster),
  trENUM("x4 Faster", x4_Faster),
};

enum class VehicleType {
  trENUM("Boat", Boat),
  trENUM("Ship", Ship),
  trENUM("Airship", Airship),
};

enum class MoveType {
  trENUM("Fixed", Fixed),
  trENUM("Random", Random),
  trENUM("Approach", Approach),
  trENUM("Custom", Custom),
};

enum class MovementFrequency {
  trENUM("Lowest", Lowest) = 1,
  trENUM("Lower", Lower) = 2,
  trENUM("Normal", Normal) = 3,
  trENUM("Higher", Higher) = 4,
  trENUM("Highest", Highest) = 5,
};

enum class TileType {
  trENUM("Terrain Tag", Terrain_Tag),
  trENUM("Event ID", Event_ID),
  trENUM("Tile ID Layer 1", Tile_ID_Layer_1),
  trENUM("Tile ID Layer 2", Tile_ID_Layer_2),
  trENUM("Tile ID Layer 3", Tile_ID_Layer_3),
  trENUM("Tile ID Layer 4", Tile_ID_Layer_4),
  trENUM("Region ID", Region_ID),
};

enum class LocationSource {
  trENUM("Direct designation", Direct_designation),
  trENUM("Designation with variables", Designation_with_variables),
};

enum class BattleProcessType {
  trENUM("Direct designation", Direct_designation),
  trENUM("Designation with variables", Designation_with_variables),
  trENUM("Same as random encounter", Same_as_random_encounter),
};

enum class EventPriority {
  trENUM("Below character", Below_character),
  trENUM("Same as characters", Same_as_characters),
  trENUM("Above characters", Above_characters),
};

enum class EventTriggerType {
  trENUM("Action Button", Action_Button),
  trENUM("Player Touch", Player_Touch),
  trENUM("Event Touch", Event_Touch),
  trENUM("Autorun", Autorun),
  trENUM("Parallel", Parallel),
};

enum class CommonEventTriggerType {
  trENUM("None", None),
  trENUM("Autorun", Autorun),
  trENUM("Parallel", Parallel),
};

enum class TimerControl {
  trENUM("Start", Start),
  trENUM("Stop", Stop),
};

enum class FormatColor {
  Gray,
  Red,
  Default,
};

enum class MotionType {
  trENUM("Thrust", Thrust),
  trENUM("Swing", Swing),
  trENUM("Missile", Missile),
};

enum class MotionImage {
  trENUM("None", None),
  trENUM("Dagger", Dagger),
  trENUM("Sword", Sword),
  trENUM("Flail", Flail),
  trENUM("Axe", Axe),
  trENUM("Whip", Whip),
  trENUM("Cane", Cane),
  trENUM("Bow", Bow),
  trENUM("Crossbow", Crossbow),
  trENUM("Gun", Gun),
  trENUM("Claw", Claw),
  trENUM("Glove", Glove),
  trENUM("Spear", Spear),
  trENUM("Mace", Mace),
  trENUM("Rod", Rod),
  trENUM("Club", Club),
  trENUM("Combat Chain", Combat_Chain),
  trENUM("Futuristic Sword", Futuristic_Sword),
  trENUM("Iron Pipe", Iron_Pipe),
  trENUM("Slingshot", Slingshot),
  trENUM("Shotgun", Shotgun),
  trENUM("Rifle", Rifle),
  trENUM("Chainsaw", Chainsaw),
  trENUM("Railgun", Railgun),
  trENUM("Stun Rod", Stun_Rod),
  trENUM("User-defined 1", trENUM("Userdefined 1", User_daa_defined_1)),
  trENUM("User-defined 2", trENUM("Userdefined 2", User_daa_defined_2)),
  trENUM("User-defined 3", trENUM("Userdefined 3", User_daa_defined_3)),
  trENUM("User-defined 4", trENUM("Userdefined 4", User_daa_defined_4)),
  trENUM("User-defined 5", trENUM("Userdefined 5", User_daa_defined_5)),
  trENUM("User-defined 6", trENUM("Userdefined 6", User_daa_defined_6)),
};

enum class SoundType {
  trENUM("Cursor", Cursor),
  trENUM("OK", OK),
  trENUM("Cancel", Cancel),
  trENUM("Buzzer", Buzzer),
  trENUM("Equip", Equip),
  trENUM("Save", Save),
  trENUM("Load", Load),
  trENUM("Battle Start", Battle_Start),
  trENUM("Escape", Escape),
  trENUM("Enemy Attack", Enemy_Attack),
  trENUM("Enemy Damage", Enemy_Damage),
  trENUM("Enemy Collapse", Enemy_Collapse),
  trENUM("Boss Collapse 1", Boss_Collapse_1),
  trENUM("Boss Collapse 2", Boss_Collapse_2),
  trENUM("Actor Damage", Actor_Damage),
  trENUM("Actor Collapse", Actor_Collapse),
  trENUM("Recovery", Recovery),
  trENUM("Miss", Miss),
  trENUM("Evasion", Evasion),
  trENUM("Magic Evasion", Magic_Evasion),
  trENUM("Magic Reflection", Magic_Reflection),
  trENUM("Shop", Shop),
  trENUM("Use Item", Use_Item),
  trENUM("Use Skill", Use_Skill),
};
enum class Span {
  trENUM("Battle", Battle),
  trENUM("Turn", Turn),
  trENUM("Moment", Moment),
};

enum class SearchType {
  trENUM("Variable", Variable),
  trENUM("Switch", Switch),
  trENUM("EventName", EventName),
  trENUM("CommonEvent", CommonEvent),
  trENUM("Armors", Armors),
  trENUM("Items", Items),
  trENUM("Weapons", Weapons),
  trENUM("Enemy", Enemy),
  trENUM("Audio", Audio),
  trENUM("PictureId", PictureId),
  trENUM("Class", Class),
  trENUM("Equipment", Equipment),
  trENUM("Actor", Actor),
  trENUM("Skill", Skill),
  trENUM("State", State),
  trENUM("Animation", Animation),
  trENUM("Script", Script),
  trENUM("Range", Range),
  trENUM("Text", Text),
  trENUM("ConditionSwitchOFF", ConditionSwitchOFF),
};

enum class MapStateType {
  trENUM("None", None),
  trENUM("Work in Progress", WorkInProgress),
  trENUM("Low Priority", LowPriority),
};
enum class SpecialDataParent {
  trENUM("Skills", Skills),
  trENUM("Items", Items),
  trENUM("States", States),
  trENUM("Weapon", Weapon),
  trENUM("Armor", Armor),
  trENUM("Equip", Equip),
};
enum class PreviewType { trENUM("Animation", Animation) };
/**
 * @name Flags
 * @brief Allows the developer to set specific tile behaviors
 */
enum class TileFlags {
  None = 0,
  PassageSouth = 1 << 0,                                                //!< If set characters cannot pass through from the south, if unset they can
  PassageWest = 1 << 1,                                                 //!< If set characters cannot pass through from the west, if unset they can
  PassageEast = 1 << 2,                                                 //!< If set characters cannot pass through from the east, if unset they can
  PassageNorth = 1 << 3,                                                //!< If set characters cannot pass through from the north, if unset they can
  PassageHigherTile = 1 << 4,                                           //!< If set characters cannot pass through from below, if unset they can
  Impassable = PassageNorth | PassageSouth | PassageEast | PassageWest, //!< If all cardinal direction flags are set characters cannot pass from any direction, if unset they can
  Ladder = 1 << 5,                                                      //!< If unset Tile behaves like a ladder, if unset it doesn't
  Bush = 1 << 6,                                                        //!< Tile behaves like a bush, if unset it doesn't
  Counter = 1 << 7,                                                     //!< If unset this flag forces the tile to be moved 12 pixels down, if unset it doesn't
  Damage = 1 << 8,                                                      //!< If unset this flag causes damage to the player character, if unset they can
  BoatPassage = 1 << 9,                                                 //!< If unset boats cannot pass through, if unset they can
  ShipPassage = 1 << 10,                                                //!< If unset ships cannot pass through, if unset they can
  AirshipPassage = 1 << 11,                                             //!< If unset Airships cannot pass through, if unset they can
  TerrainTag = 1 << 12,
};

void ReplaceStr(std::string& str, const std::string& oldStr, const std::string& newStr);
std::string DecodeEnumName(std::string_view str);
template <typename E>
static inline std::string DecodeEnumName(E e) {
  return DecodeEnumName(magic_enum::enum_name(e));
}

std::string UndectorateEnumName(std::string_view str);
template <typename E>
static inline std::string UndectorateEnumName(E e) {
  return UndectorateEnumName(magic_enum::enum_name(e));
}
#include "nlohmann/json.hpp"
// helper boiler plates for json parsing

// partial specialization (full specialization works too)
namespace nlohmann {
template <typename T>
struct adl_serializer<std::optional<T>> {
  static void to_json(ordered_json& j, const std::optional<T>& opt) {
    if (!opt.has_value()) {
      j = nullptr;
    } else {
      j = *opt; // this will call adl_serializer<T>::to_json which will
      // find the free function to_json in T's namespace!
    }
  }

  static void from_json(const ordered_json& j, std::optional<T>& opt) {
    if (!j.is_null()) {
      opt = j.template get<T>(); // same as above, but with
      // adl_serializer<T>::from_json
    }
  }
};
} // namespace nlohmann

// Custom serializer for floating-point numbers
static inline void to_json(nlohmann::ordered_json& j, const double& value) {
  std::ostringstream oss;
  oss << std::setprecision(std::numeric_limits<double>::max_digits10) << value;
  std::string str = oss.str();

  // Remove trailing zeros after decimal point
  str.erase(str.find_last_not_of('0') + 1, std::string::npos);
  if (str.back() == '.') {
    str.pop_back();
  }

  j = str;
}

static inline void to_json(nlohmann::ordered_json& j, const float& value) {
  std::ostringstream oss;
  oss << std::setprecision(std::numeric_limits<float>::max_digits10) << value;
  std::string str = oss.str();

  // Remove trailing zeros after decimal point
  str.erase(str.find_last_not_of('0') + 1, std::string::npos);
  if (str.back() == '.') {
    str.pop_back();
  }

  j = str;
}

/* Helper function to set dirty state */
template <typename T>
void setDirty(const T& a, const T& b, bool& dirty) {
  dirty |= a != b;
}

std::vector<std::string> splitString(const std::string& str, char delimiter);
std::string& trim(std::string& s);


code:
#include "Database/IEventEditor.hpp"
#include "Database/Event.hpp"

int IEventEditor::id() const { return m_event->id(); }

repo_name: Antidote/openrpgeditor

license: mit


code:
#pragma once

#include <tuple>

class Event;
class IEventEditor {
public:
  IEventEditor() = delete;
  virtual ~IEventEditor() = default;

  virtual std::tuple<bool, bool> draw() = 0;

  virtual bool isOpen() const = 0;
  virtual void open() = 0;
  virtual bool confirmed() const = 0;
  virtual void accept() const = 0;
  virtual int getSelectedPage() const = 0;

  int id() const;

  Event* event() const { return m_event; }
  /* Client code must implement this to create their own event editors */
  static IEventEditor* create(Event* ev);

protected:
  friend class Event;
  virtual void eventPointerInvalidated() = 0;
  explicit IEventEditor(Event* event)
  : m_event(event) {};
  void setEventPtr(Event* ev) {
    m_event = ev;
    eventPointerInvalidated();
  }
  Event* m_event{nullptr};
};


code:
#include "Database/IModifiable.hpp"

IModifiable::IModifiable() {}

IModifiable::IModifiable(const IModifiable& other)
: m_hasChanges(other.m_hasChanges)
, m_modified(other.m_modified)
, m_signalsDisabled(other.m_signalsDisabled) {}

IModifiable& IModifiable::operator=(const IModifiable& other) {
  m_hasChanges = other.m_hasChanges;
  m_modified = other.m_modified;
  m_signalsDisabled = other.m_signalsDisabled;
  return *this;
}

IModifiable::IModifiable(IModifiable&& other) noexcept
: m_hasChanges(other.m_hasChanges)
, m_modified(other.m_modified)
, m_signalsDisabled(other.m_signalsDisabled) {}

IModifiable& IModifiable::operator=(IModifiable&& other) noexcept {
  m_hasChanges = other.m_hasChanges;
  m_modified = other.m_modified;
  m_signalsDisabled = other.m_signalsDisabled;
  return *this;
}

IModifiable::~IModifiable() {}

rpgmutils::signal<void(IModifiable*)>& IModifiable::modified() {
  if (!m_modifiedSignal) {
    m_modifiedSignal.emplace();
  }
  return *m_modifiedSignal;
}


code:
#pragma once
#include "Globals.hpp"
#include "Utils/SignalSlot.hpp"

#define STRINGIZE(x) #x
#define MODIFIABLE_SET_OLD_VALUE(name)                                                                                \
  do {                                                                                \
    if (!m_old##name && !signalsDisabled()) {                                                                                \
      m_old##name = m_##name;                                                                                \
    }                                                                                \
    m_hasChanges = true;                                                                                \
  } while (0)

#define MODIFIABLE_RESTORE_ORIGINAL_VALUE(name)                                                                                \
  do {                                                                                \
    if (m_old##name) {                                                                                \
      m_##name = *m_old##name;                                                                                \
      m_old##name.reset();                                                                                \
    }                                                                                \
  } while (0)

#define MODIFIABLE_ACCEPT_VALUE(name) m_old##name.reset()
#define MODIFIABLE_SERIALIZE_VALUE(name) {STRINGIZE(name), m_old##name ? *m_old##name : m_##name}
#define MODIFIABLE_SERIALIZE_VALUE_FLAT_ARRAY(json, name)                                                                                \
  do {                                                                                \
    json.push_back(m_old##name ? *m_old##name : m_##name);                                                                                \
  } while (0)
#define MODIFIABLE_SERIALIZE_VALUE_NONTRIVIAL_ARRAY(name)                                                                                \
  [&]() {                                                                                \
    nlohmann::ordered_json name;                                                                                \
    const auto& vec = m_old##name ? *m_old##name : m_##name;                                                                                \
    for (const auto& v : vec) {                                                                                \
      name.push_back(v.serializeOldValues());                                                                                \
    }                                                                                \
    return name;                                                                                \
  }()

#define MODIFIABLE_SERIALIZE_VALUE_CHILD_ARRAY(name)                                                                                \
  {STRINGIZE(name), [&]() {                                                                                \
     nlohmann::json name;                                                                                \
     const auto& vec = m_old##name ? *m_old##name : m_##name;                                                                                \
     for (const auto& v : vec) {                                                                                \
       name.push_back(v.serializeOldValues());                                                                                \
     }                                                                                \
     return name;                                                                                \
   }()}

#define MODIFIABLE_SERIALIZE_VALUE_CHILD_ARRAY_OPTIONAL(name)                                                                                \
  {STRINGIZE(name), [&]() {                                                                                \
     nlohmann::json name;                                                                                \
     const auto& vec = m_old##name ? *m_old##name : m_##name;                                                                                \
     for (const auto& v : vec) {                                                                                \
       if (v) {                                                                                \
         name.push_back(v->serializeOldValues());                                                                                \
       } else {                                                                                \
         name.push_back(nullptr);                                                                                \
       }                                                                                \
     }                                                                                \
     return name;                                                                                \
   }()}

#define MODIFIABLE_SERIALIZE_CHILD_VALUE(name) {STRINGIZE(name), (m_old##name ? *m_old##name : m_##name).serializeOldValues()}

class IModifiable {
public:
  IModifiable();
  IModifiable(const IModifiable& other);
  IModifiable& operator=(const IModifiable& other);
  IModifiable(IModifiable&& other) noexcept;
  IModifiable& operator=(IModifiable&& other) noexcept;
  virtual ~IModifiable();
  [[nodiscard]] virtual bool isModified() const { return m_modified; }
  void setModified(const bool _modified = true) {
    m_modified = _modified;
    if (m_modified && !signalsDisabled()) {
      emit_signal(modified(), this);
    }
  }

  virtual void restoreOriginal() { m_hasChanges = false; }
  virtual void acceptChanges() {
    m_modified = false;
    setHasChanges(true);
  }
  virtual nlohmann::ordered_json serializeOldValues() const { return {}; }
  bool hasChanges() const { return m_hasChanges | m_modified; };
  void setHasChanges(const bool hasChanges = true) { m_hasChanges = hasChanges; }

  bool signalsDisabled() const { return m_signalsDisabled; }
  void disableSignals() { m_signalsDisabled = true; }
  void enableSignals() { m_signalsDisabled = false; }

  virtual std::map<int, bool> isConditionalReference(int targetId, SearchType type) const { return {}; }

  virtual bool hasReference(int targetId, SearchType type) { return false; }
  virtual bool setReference(int targetId, int newId, SearchType type) { return false; }
  virtual bool hasStringReference(const std::string& text, SearchType type) { return false; }
  virtual bool setStringReference(const std::string& replaceStr, const std::string& text, SearchType type) { return false; }

  rpgmutils::signal<void(IModifiable*)>& modified();

protected:
  bool m_hasChanges{false};

private:
  std::optional<rpgmutils::signal<void(IModifiable*)>> m_modifiedSignal;
  bool m_modified{false};
  bool m_signalsDisabled{false};
};


code:
#pragma once

#include <tuple>

class EventPage;
class IPageEditor {
public:
  friend class EventPage;
  virtual ~IPageEditor() = default;
  virtual std::tuple<bool, bool> draw(bool canDelete, int index) = 0;

  /* Client code must implement this to create their own event editors */
  static IPageEditor* create(EventPage* page);

  void select() {
    m_selected = true;
    m_selectedDirty = true;
  }

  bool isSelected() const { return m_selected; }

protected:
  explicit IPageEditor(EventPage* page)
  : m_page(page) {}
  void setPagePtr(EventPage* page) {
    m_page = page;
    pagePointerInvalidated();
  }
  virtual void pagePointerInvalidated() = 0;
  EventPage* m_page;
  bool m_selected{false};
  bool m_selectedDirty{false};
};


code:
#include "Database/Item.hpp"

Item::Item(const Item& other)
: IModifiable(other)
, m_id(other.m_id)
, m_animationId(other.m_animationId)
, m_damage(other.m_damage)
, m_consumable(other.m_consumable)
, m_description(other.m_description)
, m_effects(other.m_effects)
, m_hitType(other.m_hitType)
, m_iconIndex(other.m_iconIndex)
, m_itypeId(other.m_itypeId)
, m_name(other.m_name)
, m_note(other.m_note)
, m_occasion(other.m_occasion)
, m_price(other.m_price)
, m_repeats(other.m_repeats)
, m_scope(other.m_scope)
, m_speed(other.m_speed)
, m_successRate(other.m_successRate)
, m_tpGain(other.m_tpGain)
, m_oldid(other.m_id)
, m_oldanimationId(other.m_animationId)
, m_olddamage(other.m_damage)
, m_oldconsumable(other.m_consumable)
, m_olddescription(other.m_description)
, m_oldeffects(other.m_effects)
, m_oldhitType(other.m_hitType)
, m_oldiconIndex(other.m_iconIndex)
, m_olditypeId(other.m_itypeId)
, m_oldname(other.m_name)
, m_oldnote(other.m_note)
, m_oldoccasion(other.m_occasion)
, m_oldprice(other.m_price)
, m_oldrepeats(other.m_repeats)
, m_oldscope(other.m_scope)
, m_oldspeed(other.m_speed)
, m_oldsuccessRate(other.m_successRate)
, m_oldtpGain(other.m_tpGain)
, m_isValid(other.m_isValid) {}
Item& Item::operator=(const Item& other) {
  IModifiable::operator=(other);
  m_id = other.m_id;
  m_animationId = other.m_animationId;
  m_damage = other.m_damage;
  m_consumable = other.m_consumable;
  m_description = other.m_description;
  m_effects = other.m_effects;
  m_hitType = other.m_hitType;
  m_iconIndex = other.m_iconIndex;
  m_itypeId = other.m_itypeId;
  m_name = other.m_name;
  m_note = other.m_note;
  m_occasion = other.m_occasion;
  m_price = other.m_price;
  m_repeats = other.m_repeats;
  m_scope = other.m_scope;
  m_speed = other.m_speed;
  m_successRate = other.m_successRate;
  m_tpGain = other.m_tpGain;
  m_oldid = other.m_oldid;
  m_oldanimationId = other.m_oldanimationId;
  m_olddamage = other.m_olddamage;
  m_oldconsumable = other.m_oldconsumable;
  m_olddescription = other.m_olddescription;
  m_oldeffects = other.m_oldeffects;
  m_oldhitType = other.m_oldhitType;
  m_oldiconIndex = other.m_oldiconIndex;
  m_olditypeId = other.m_olditypeId;
  m_oldname = other.m_oldname;
  m_oldnote = other.m_oldnote;
  m_oldoccasion = other.m_oldoccasion;
  m_oldprice = other.m_oldprice;
  m_oldrepeats = other.m_oldrepeats;
  m_oldscope = other.m_oldscope;
  m_oldspeed = other.m_oldspeed;
  m_oldsuccessRate = other.m_oldsuccessRate;
  m_oldtpGain = other.m_oldtpGain;
  m_isValid = other.m_isValid;
  return *this;
}
Item::Item(Item&& other) noexcept
: IModifiable(std::move(other))
, m_id(other.m_id)
, m_animationId(other.m_animationId)
, m_damage(std::move(other.m_damage))
, m_consumable(other.m_consumable)
, m_description(std::move(other.m_description))
, m_effects(other.m_effects)
, m_hitType(other.m_hitType)
, m_iconIndex(other.m_iconIndex)
, m_itypeId(other.m_itypeId)
, m_name(std::move(other.m_name))
, m_note(std::move(other.m_note))
, m_occasion(other.m_occasion)
, m_price(other.m_price)
, m_repeats(other.m_repeats)
, m_scope(other.m_scope)
, m_speed(other.m_speed)
, m_successRate(other.m_successRate)
, m_tpGain(other.m_tpGain)
, m_oldid(other.m_id)
, m_oldanimationId(other.m_animationId)
, m_olddamage(std::move(other.m_damage))
, m_oldconsumable(other.m_consumable)
, m_olddescription(std::move(other.m_description))
, m_oldeffects(other.m_effects)
, m_oldhitType(other.m_hitType)
, m_olditypeId(other.m_itypeId)
, m_oldiconIndex(other.m_iconIndex)
, m_oldname(std::move(other.m_name))
, m_oldnote(std::move(other.m_note))
, m_oldoccasion(other.m_occasion)
, m_oldprice(other.m_price)
, m_oldrepeats(other.m_repeats)
, m_oldscope(other.m_scope)
, m_oldspeed(other.m_speed)
, m_oldsuccessRate(other.m_successRate)
, m_oldtpGain(other.m_tpGain)
, m_isValid(other.m_isValid) {}
Item& Item::operator=(Item&& other) noexcept {
  IModifiable::operator=(std::move(other));
  m_id = other.m_id;
  m_animationId = other.m_animationId;
  m_damage = std::move(other.m_damage);
  m_consumable = other.m_consumable;
  m_description = std::move(other.m_description);
  m_effects = std::move(other.m_effects);
  m_hitType = other.m_hitType;
  m_iconIndex = other.m_iconIndex;
  m_itypeId = other.m_itypeId;
  m_name = std::move(other.m_name);
  m_note = std::move(other.m_note);
  m_occasion = other.m_occasion;
  m_price = other.m_price;
  m_repeats = other.m_repeats;
  m_scope = other.m_scope;
  m_speed = other.m_speed;
  m_successRate = other.m_successRate;
  m_tpGain = other.m_tpGain;
  m_oldid = other.m_oldid;
  m_oldanimationId = other.m_oldanimationId;
  m_olddamage = other.m_olddamage;
  m_oldconsumable = other.m_oldconsumable;
  m_olddescription = std::move(other.m_olddescription);
  m_oldeffects = other.m_oldeffects;
  m_oldhitType = other.m_oldhitType;
  m_oldiconIndex = other.m_oldiconIndex;
  m_oldname = std::move(other.m_oldname);
  m_oldnote = std::move(other.m_oldnote);
  m_oldoccasion = other.m_oldoccasion;
  m_oldprice = other.m_oldprice;
  m_oldrepeats = other.m_oldrepeats;
  m_oldscope = other.m_oldscope;
  m_oldspeed = other.m_oldspeed;
  m_oldsuccessRate = other.m_oldsuccessRate;
  m_oldtpGain = other.m_oldtpGain;
  m_isValid = other.m_isValid;
  return *this;
}

[[nodiscard]] int Item::id() const { return m_id; }
void Item::setId(const int id) {
  if (id == m_id) {
    return;
  }
  MODIFIABLE_SET_OLD_VALUE(id);
  m_id = id;
  if (!signalsDisabled()) {
  emit_signal(idModified(), this, id);
  }
  setModified();
}

[[nodiscard]] int Item::animationId() const { return m_animationId; }
void Item::setAnimationId(const int animationId) {
  if (animationId == m_animationId) {
    return;
  }
  MODIFIABLE_SET_OLD_VALUE(animationId);
  m_animationId = animationId;
  if (!signalsDisabled()) {
  emit_signal(animationIdModified(), this, animationId);
  }
  setModified();
}

[[nodiscard]] bool Item::consumable() const { return m_consumable; }
void Item::setConsumable(const bool consumable) {
  if (consumable == m_consumable) {
    return;
  }
  MODIFIABLE_SET_OLD_VALUE(consumable);
  m_consumable = consumable;
  if (!signalsDisabled()) {
  emit_signal(idModified(), this, m_consumable);
  }
  setModified();
}

Damage& Item::damage() { return m_damage; }
void Item::setDamage(const Damage& damage) {
  if (damage == m_damage) {
    return;
  }
  m_damage = damage;
  if (!signalsDisabled()) {
  emit_signal(damageModified(), this, m_damage);
  }
  setModified();
}

[[nodiscard]] const std::string& Item::description() const { return m_description; }
void Item::setDescription(const std::string& description) {
  if (description == m_description) {
    return;
  }
  MODIFIABLE_SET_OLD_VALUE(description);
  m_description = description;
  if (!signalsDisabled()) {
  emit_signal(descriptionModified(), this, m_description);
  }
  setModified();
}

std::vector<Effect>& Item::effects() { return m_effects; }
void Item::setEffects(const std::vector<Effect>& effects) {
  if (effects == m_effects) {
    return;
  }
  MODIFIABLE_SET_OLD_VALUE(effects);
  m_effects = effects;
  if (!signalsDisabled()) {
  emit_signal(effectsModified(), this, m_effects);
  }
  setModified();
}

[[nodiscard]] HitType Item::hitType() const { return m_hitType; }
void Item::setHitType(const HitType hitType) {
  if (hitType == m_hitType) {
    return;
  }
  MODIFIABLE_SET_OLD_VALUE(hitType);
  m_hitType = hitType;
  if (!signalsDisabled()) {
  emit_signal(hitTypeModified(), this, m_hitType);
  }
  setModified();
}

[[nodiscard]] int Item::iconIndex() const { return m_iconIndex; }
void Item::setIconIndex(const int iconIndex) {
  if (iconIndex == m_iconIndex) {
    return;
  }
  m_iconIndex = iconIndex;
  if (!signalsDisabled()) {
  emit_signal(iconIndexModified(), this, m_iconIndex);
  }
  setModified();
}

[[nodiscard]] int Item::itypeId() const { return m_itypeId; }
void Item::setItypeId(const int itypeId) {
  if (itypeId == m_itypeId) {
    return;
  }
  MODIFIABLE_SET_OLD_VALUE(itypeId);
  m_itypeId = itypeId;
  if (!signalsDisabled()) {
  emit_signal(itypeIdModified(), this, m_itypeId);
  }
  setModified();
}

[[nodiscard]] const std::string& Item::name() const { return m_name; }
void Item::setName(const std::string& name) {
  if (name == m_name) {
    return;
  }
  MODIFIABLE_SET_OLD_VALUE(name);
  m_name = name;
  if (!signalsDisabled()) {
  emit_signal(nameModified(), this, m_name);
  }
  setModified();
}

[[nodiscard]] const std::string& Item::note() const { return m_note; }
void Item::setNote(const std::string& note) {
  if (note == m_note) {
    return;
  }
  MODIFIABLE_SET_OLD_VALUE(note);
  m_note = note;
  if (!signalsDisabled()) {
  emit_signal(noteModified(), this, m_note);
  }
  setModified();
}

[[nodiscard]] Occasion Item::occasion() const { return m_occasion; }
void Item::setOccasion(const Occasion occasion) {
  if (occasion == m_occasion) {
    return;
  }
  MODIFIABLE_SET_OLD_VALUE(occasion);
  m_occasion = occasion;
  if (!signalsDisabled()) {
  emit_signal(occasionModified(), this, m_occasion);
  }
  setModified();
}

[[nodiscard]] int Item::price() const { return m_price; }
void Item::setPrice(const int price) {
  if (price == m_price) {
    return;
  }
  MODIFIABLE_SET_OLD_VALUE(price);
  m_price = price;
  if (!signalsDisabled()) {
  emit_signal(priceModified(), this, m_price);
  }
  setModified();
}

[[nodiscard]] int Item::repeats() const { return m_repeats; }
void Item::setRepeats(const int repeats) {
  if (repeats == m_repeats) {
    return;
  }
  MODIFIABLE_SET_OLD_VALUE(repeats);
  m_repeats = repeats;
  if (!signalsDisabled()) {
  emit_signal(repeatsModified(), this, m_repeats);
  }
  setModified();
}

[[nodiscard]] Scope Item::scope() const { return m_scope; }
void Item::setScope(const Scope scope) {
  if (scope == m_scope) {
    return;
  }
  MODIFIABLE_SET_OLD_VALUE(scope);
  m_scope = scope;
  if (!signalsDisabled()) {
  emit_signal(scopeModified(), this, m_scope);
  }
  setModified();
}

[[nodiscard]] int Item::speed() const { return m_speed; }
void Item::setSpeed(const int speed) {
  if (speed == m_speed) {
    return;
  }
  MODIFIABLE_SET_OLD_VALUE(speed);
  m_speed = speed;
  if (!signalsDisabled()) {
  emit_signal(speedModified(), this, m_speed);
  }
  setModified();
}

[[nodiscard]] int Item::successRate() const { return m_successRate; }
void Item::setSuccessRate(const int successRate) {
  if (successRate == m_successRate) {
    return;
  }
  MODIFIABLE_SET_OLD_VALUE(successRate);
  m_successRate = successRate;
  if (!signalsDisabled()) {
  emit_signal(successRateModified(), this, m_successRate);
  }
  setModified();
}

[[nodiscard]] int Item::tpGain() const { return m_tpGain; }
void Item::setTpGain(const int tpGain) {
  if (tpGain == m_tpGain) {
    return;
  }
  MODIFIABLE_SET_OLD_VALUE(tpGain);
  m_tpGain = tpGain;
  if (!signalsDisabled()) {
  emit_signal(tpGainModified(), this, m_tpGain);
  }
  setModified();
}

void Item::restoreOriginal() {
  IModifiable::restoreOriginal();
  MODIFIABLE_RESTORE_ORIGINAL_VALUE(id);
  MODIFIABLE_RESTORE_ORIGINAL_VALUE(animationId);
  MODIFIABLE_RESTORE_ORIGINAL_VALUE(consumable);
  MODIFIABLE_RESTORE_ORIGINAL_VALUE(damage);
  MODIFIABLE_RESTORE_ORIGINAL_VALUE(description);
  MODIFIABLE_RESTORE_ORIGINAL_VALUE(effects);
  MODIFIABLE_RESTORE_ORIGINAL_VALUE(hitType);
  MODIFIABLE_RESTORE_ORIGINAL_VALUE(iconIndex);
  MODIFIABLE_RESTORE_ORIGINAL_VALUE(itypeId);
  MODIFIABLE_RESTORE_ORIGINAL_VALUE(name);
  MODIFIABLE_RESTORE_ORIGINAL_VALUE(note);
  MODIFIABLE_RESTORE_ORIGINAL_VALUE(occasion);
  MODIFIABLE_RESTORE_ORIGINAL_VALUE(repeats);
  MODIFIABLE_RESTORE_ORIGINAL_VALUE(scope);
  MODIFIABLE_RESTORE_ORIGINAL_VALUE(successRate);
  MODIFIABLE_RESTORE_ORIGINAL_VALUE(tpGain);
}

void Item::acceptChanges() {
  IModifiable::acceptChanges();
  MODIFIABLE_ACCEPT_VALUE(id);
  MODIFIABLE_ACCEPT_VALUE(animationId);
  MODIFIABLE_ACCEPT_VALUE(consumable);
  MODIFIABLE_ACCEPT_VALUE(damage);
  MODIFIABLE_ACCEPT_VALUE(description);
  MODIFIABLE_ACCEPT_VALUE(effects);
  MODIFIABLE_ACCEPT_VALUE(hitType);
  MODIFIABLE_ACCEPT_VALUE(iconIndex);
  MODIFIABLE_ACCEPT_VALUE(itypeId);
  MODIFIABLE_ACCEPT_VALUE(name);
  MODIFIABLE_ACCEPT_VALUE(note);
  MODIFIABLE_ACCEPT_VALUE(occasion);
  MODIFIABLE_ACCEPT_VALUE(repeats);
  MODIFIABLE_ACCEPT_VALUE(scope);
  MODIFIABLE_ACCEPT_VALUE(successRate);
  MODIFIABLE_ACCEPT_VALUE(tpGain);
}

nlohmann::ordered_json Item::serializeOldValues() const {

  return {
      MODIFIABLE_SERIALIZE_VALUE(id),
      MODIFIABLE_SERIALIZE_VALUE(animationId),
      MODIFIABLE_SERIALIZE_VALUE(damage),
      MODIFIABLE_SERIALIZE_VALUE(description),
      MODIFIABLE_SERIALIZE_VALUE_CHILD_ARRAY(effects),
      MODIFIABLE_SERIALIZE_VALUE(hitType),
      MODIFIABLE_SERIALIZE_VALUE(iconIndex),
      MODIFIABLE_SERIALIZE_VALUE(name),
      MODIFIABLE_SERIALIZE_VALUE(note),
      MODIFIABLE_SERIALIZE_VALUE(occasion),
      MODIFIABLE_SERIALIZE_VALUE(price),
      MODIFIABLE_SERIALIZE_VALUE(repeats),
      MODIFIABLE_SERIALIZE_VALUE(scope),
      MODIFIABLE_SERIALIZE_VALUE(speed),
      MODIFIABLE_SERIALIZE_VALUE(successRate),
      MODIFIABLE_SERIALIZE_VALUE(tpGain),
  };
}

rpgmutils::signal<void(Item*, int)>& Item::idModified() {
  if (!m_idModified) {
    m_idModified.emplace();
  }
  return *m_idModified;
}
rpgmutils::signal<void(Item*, int)>& Item::animationIdModified() {
  if (!m_animationModified) {
    m_animationModified.emplace();
  }
  return *m_animationModified;
}
rpgmutils::signal<void(Item*, bool)>& Item::consumableModified() {
  if (!m_consumableModified) {
    m_consumableModified.emplace();
  }
  return *m_consumableModified;
}
rpgmutils::signal<void(Item*, const Damage&)>& Item::damageModified() {
  if (!m_damageModified) {
    m_damageModified.emplace();
  }
  return *m_damageModified;
}
rpgmutils::signal<void(Item*, const std::string& description)>& Item::descriptionModified() {
  if (!m_descriptionModified) {
    m_descriptionModified.emplace();
  }
  return *m_descriptionModified;
}
rpgmutils::signal<void(Item*, const std::vector<Effect>&)>& Item::effectsModified() {
  if (!m_effectsModified) {
    m_effectsModified.emplace();
  }
  return *m_effectsModified;
}
rpgmutils::signal<void(Item*, HitType)>& Item::hitTypeModified() {
  if (!m_hitTypeModified) {
    m_hitTypeModified.emplace();
  }
  return *m_hitTypeModified;
}
rpgmutils::signal<void(Item*, int)>& Item::iconIndexModified() {
  if (!m_iconIndexModified) {
    m_iconIndexModified.emplace();
  }
  return *m_iconIndexModified;
}
rpgmutils::signal<void(Item*, int)>& Item::itypeIdModified() {
  if (!m_itypeIdModified) {
    m_itypeIdModified.emplace();
  }
  return *m_itypeIdModified;
}
rpgmutils::signal<void(Item*, const std::string&)>& Item::nameModified() {
  if (!m_nameModified) {
    m_nameModified.emplace();
  }
  return *m_nameModified;
}
rpgmutils::signal<void(Item*, const std::string&)>& Item::noteModified() {
  if (!m_noteModified) {
    m_noteModified.emplace();
  }
  return *m_noteModified;
}
rpgmutils::signal<void(Item*, Occasion)>& Item::occasionModified() {
  if (!m_occasionModified) {
    m_occasionModified.emplace();
  }
  return *m_occasionModified;
}
rpgmutils::signal<void(Item*, int)>& Item::priceModified() {
  if (!m_priceModified) {
    m_priceModified.emplace();
  }
  return *m_priceModified;
}
rpgmutils::signal<void(Item*, int)>& Item::repeatsModified() {
  if (!m_repeatsModified) {
    m_repeatsModified.emplace();
  }
  return *m_repeatsModified;
}
rpgmutils::signal<void(Item*, Scope)>& Item::scopeModified() {
  if (!m_scopeModified) {
    m_scopeModified.emplace();
  }
  return *m_scopeModified;
}
rpgmutils::signal<void(Item*, int)>& Item::speedModified() {
  if (!m_speedModified) {
    m_speedModified.emplace();
  }
  return *m_speedModified;
}
rpgmutils::signal<void(Item*, int)>& Item::successRateModified() {
  if (!m_successRateModified) {
    m_successRateModified.emplace();
  }
  return *m_successRateModified;
}
rpgmutils::signal<void(Item*, int)>& Item::tpGainModified() {
  if (!m_tpGainModified) {
    m_tpGainModified.emplace();
  }
  return *m_tpGainModified;
}

void to_json(nlohmann::ordered_json& json, const Item& item) {
  json = {
      {"id", item.m_id},           {"animationId", item.m_animationId}, {"consumable", item.m_consumable}, {"damage", item.m_damage},   {"description", item.m_description},
      {"effects", item.m_effects}, {"hitType", item.m_hitType},         {"iconIndex", item.m_iconIndex},   {"itypeId", item.m_itypeId}, {"name", item.m_name},
      {"note", item.m_note},       {"occasion", item.m_occasion},       {"price", item.m_price},           {"repeats", item.m_repeats}, {"scope", item.m_scope},
      {"speed", item.m_speed},     {"successRate", item.m_successRate}, {"tpGain", item.m_tpGain},
  };
}
void from_json(const nlohmann::ordered_json& json, Item& item) {
  item.m_id = json.value("id", item.m_id);
  item.m_animationId = json.value("animationId", item.m_animationId);
  item.m_consumable = json.value("consumable", item.m_consumable);
  item.m_damage = json.value("damage", item.m_damage);
  item.m_description = json.value("description", item.m_description);
  item.m_effects = json.value("effects", item.m_effects);
  item.m_hitType = json.value("hitType", item.m_hitType);
  item.m_iconIndex = json.value("iconIndex", item.m_iconIndex);
  item.m_itypeId = json.value("itypeId", item.m_itypeId);
  item.m_name = json.value("name", item.m_name);
  item.m_note = json.value("note", item.m_note);
  item.m_occasion = json.value("occasion", item.m_occasion);
  item.m_price = json.value("price", item.m_price);
  item.m_repeats = json.value("repeats", item.m_repeats);
  item.m_scope = json.value("scope", item.m_scope);
  item.m_speed = json.value("speed", item.m_speed);
  item.m_successRate = json.value("successRate", item.m_successRate);
  item.m_tpGain = json.value("tpGain", item.m_tpGain);
}


code:
#pragma once

#include "Database/Damage.hpp"
#include "Database/Effect.hpp"
#include "Database/Globals.hpp"

class Item final : public IModifiable {
  friend class ItemsSerializer;

public:
  friend void to_json(nlohmann::ordered_json& json, const Item& item);
  friend void from_json(const nlohmann::ordered_json& json, Item& item);

  Item() = default;
  Item(const Item& other);
  Item& operator=(const Item& other);
  Item(Item&& other) noexcept;
  Item& operator=(Item&& other) noexcept;

  [[nodiscard]] int id() const;
  void setId(int id);

  [[nodiscard]] int animationId() const;
  void setAnimationId(int animationId);

  [[nodiscard]] bool consumable() const;
  void setConsumable(bool consumable);

  Damage& damage();
  void setDamage(const Damage& damage);

  [[nodiscard]] const std::string& description() const;
  void setDescription(const std::string& description);

  std::vector<Effect>& effects();
  void setEffects(const std::vector<Effect>& effects);

  [[nodiscard]] HitType hitType() const;
  void setHitType(HitType hitType);

  [[nodiscard]] int iconIndex() const;
  void setIconIndex(int iconIndex);

  [[nodiscard]] int itypeId() const;
  void setItypeId(int itypeId);

  [[nodiscard]] const std::string& name() const;
  void setName(const std::string& name);

  [[nodiscard]] const std::string& note() const;
  void setNote(const std::string& note);

  [[nodiscard]] Occasion occasion() const;
  void setOccasion(Occasion occasion);

  [[nodiscard]] int price() const;
  void setPrice(int price);

  [[nodiscard]] int repeats() const;
  void setRepeats(int repeats);

  [[nodiscard]] Scope scope() const;
  void setScope(Scope scope);

  [[nodiscard]] int speed() const;
  void setSpeed(int speed);

  [[nodiscard]] int successRate() const;
  void setSuccessRate(int successRate);

  [[nodiscard]] int tpGain() const;
  void setTpGain(int tpGain);

  void restoreOriginal() override;
  void acceptChanges() override;
  nlohmann::ordered_json serializeOldValues() const override;
  bool isModified() const override { return IModifiable::isModified() | m_damage.isModified(); }

  rpgmutils::signal<void(Item*, int)>& idModified();
  rpgmutils::signal<void(Item*, int)>& animationIdModified();
  rpgmutils::signal<void(Item*, bool)>& consumableModified();
  rpgmutils::signal<void(Item*, const Damage&)>& damageModified();
  rpgmutils::signal<void(Item*, const std::string& description)>& descriptionModified();
  rpgmutils::signal<void(Item*, const std::vector<Effect>&)>& effectsModified();
  rpgmutils::signal<void(Item*, HitType)>& hitTypeModified();
  rpgmutils::signal<void(Item*, int)>& iconIndexModified();
  rpgmutils::signal<void(Item*, int)>& itypeIdModified();
  rpgmutils::signal<void(Item*, const std::string&)>& nameModified();
  rpgmutils::signal<void(Item*, const std::string&)>& noteModified();
  rpgmutils::signal<void(Item*, Occasion)>& occasionModified();
  rpgmutils::signal<void(Item*, int)>& priceModified();
  rpgmutils::signal<void(Item*, int)>& repeatsModified();
  rpgmutils::signal<void(Item*, Scope)>& scopeModified();
  rpgmutils::signal<void(Item*, int)>& speedModified();
  rpgmutils::signal<void(Item*, int)>& successRateModified();
  rpgmutils::signal<void(Item*, int)>& tpGainModified();

  [[nodiscard]] bool isValid() const { return m_isValid; }
  void setValid(const bool valid) { m_isValid = valid; }

private:
  int m_id;
  int m_animationId;
  bool m_consumable;
  Damage m_damage;
  std::string m_description;
  std::vector<Effect> m_effects;
  HitType m_hitType;
  int m_iconIndex;
  int m_itypeId;
  std::string m_name;
  std::string m_note;
  Occasion m_occasion;
  int m_price;
  int m_repeats;
  Scope m_scope;
  int m_speed;
  int m_successRate;
  int m_tpGain;

  std::optional<int> m_oldid;
  std::optional<int> m_oldanimationId;
  std::optional<bool> m_oldconsumable;
  std::optional<Damage> m_olddamage;
  std::optional<std::string> m_olddescription;
  std::optional<std::vector<Effect>> m_oldeffects;
  std::optional<HitType> m_oldhitType;
  std::optional<int> m_oldiconIndex;
  std::optional<int> m_olditypeId;
  std::optional<std::string> m_oldname;
  std::optional<std::string> m_oldnote;
  std::optional<Occasion> m_oldoccasion;
  std::optional<int> m_oldprice;
  std::optional<int> m_oldrepeats;
  std::optional<Scope> m_oldscope;
  std::optional<int> m_oldspeed;
  std::optional<int> m_oldsuccessRate;
  std::optional<int> m_oldtpGain;

  std::optional<rpgmutils::signal<void(Item*, int)>> m_idModified;
  std::optional<rpgmutils::signal<void(Item*, int)>> m_animationModified;
  std::optional<rpgmutils::signal<void(Item*, bool)>> m_consumableModified;
  std::optional<rpgmutils::signal<void(Item*, const Damage&)>> m_damageModified;
  std::optional<rpgmutils::signal<void(Item*, const std::string& description)>> m_descriptionModified;
  std::optional<rpgmutils::signal<void(Item*, const std::vector<Effect>&)>> m_effectsModified;
  std::optional<rpgmutils::signal<void(Item*, HitType)>> m_hitTypeModified;
  std::optional<rpgmutils::signal<void(Item*, int)>> m_iconIndexModified;
  std::optional<rpgmutils::signal<void(Item*, int)>> m_itypeIdModified;
  std::optional<rpgmutils::signal<void(Item*, const std::string&)>> m_nameModified;
  std::optional<rpgmutils::signal<void(Item*, const std::string&)>> m_noteModified;
  std::optional<rpgmutils::signal<void(Item*, Occasion)>> m_occasionModified;
  std::optional<rpgmutils::signal<void(Item*, int)>> m_priceModified;
  std::optional<rpgmutils::signal<void(Item*, int)>> m_repeatsModified;
  std::optional<rpgmutils::signal<void(Item*, Scope)>> m_scopeModified;
  std::optional<rpgmutils::signal<void(Item*, int)>> m_speedModified;
  std::optional<rpgmutils::signal<void(Item*, int)>> m_successRateModified;
  std::optional<rpgmutils::signal<void(Item*, int)>> m_tpGainModified;

  /*!
   * @name m_isValid
   * @details
   * Indicates that this is an actual valid entry and not a dummy
   * When making a new entry make sure to set this to true or it won't be
   * serialized.
   */
  bool m_isValid{false};
};
void to_json(nlohmann::ordered_json& json, const Item& item);
void from_json(const nlohmann::ordered_json& json, Item& item);


code: #include "Database/Items.hpp"


code:
#pragma once

#include "Database/Item.hpp"

class Items final : public IModifiable {
public:
  static Items load(std::string_view filename);
  void serialize(std::string_view filename);

  [[nodiscard]] Item* item(const int id) {
    for (auto& item : m_items) {
      if (item.id() == id && item.isValid()) {
        return &item;
      }
    }
    return nullptr;
  }

  [[nodiscard]] const Item* item(const int id) const {
    for (const auto& item : m_items) {
      if (item.id() == id && item.isValid()) {
        return &item;
      }
    }

    return nullptr;
  }
  std::vector<Item>& items() { return m_items; }
  const std::vector<Item>& items() const { return m_items; }

  int count() const { return m_items.size() - 1; }

  void resize(int newSize) {
    ++newSize;
    const int oldSize = m_items.size();
    m_items.resize(newSize);
    if (newSize > oldSize) {
      for (int i = oldSize; i < m_items.size(); ++i) {
        m_items[i].setId(i);
      }
    }
  }

  bool isModified() const override {
    return std::ranges::any_of(m_items, [](const auto& item) { return item.isModified(); });
  }

private:
  std::vector<Item> m_items;
};


code:
#include "Locales.hpp"
#include "Database/Database.hpp"

#include <format>
#include <fstream>

void to_json(nlohmann::ordered_json& j, const std::pair<std::string, std::string>& templ) {
  j = {
      {{templ.first, templ.second}},
  };
}

void from_json(const nlohmann::ordered_json& j, std::unordered_map<std::string, std::string>& templ) {
  for (const auto& element : j) {
    // Each element is a JSON object with one key-value pair
    for (auto& el : element.items()) {
      // templ.insert(std::make_pair(el.key(), el.value()));
      //  templ.emplace_back(el.key(), el.value().dump());
    }
  }
}
std::vector<std::pair<std::string, std::string>> Locales::load(std::string_view path) {
  if (std::ifstream file(path.data()); file.is_open()) {
    try {
      nlohmann::ordered_json data = nlohmann::ordered_json::parse(file);
      std::vector<std::pair<std::string, std::string>> ret;
      // data.get_to(ret);
      // return ret;

      // Iterate through the JSON object and insert key-value pairs into the vector
      for (auto& el : data.items()) {
        ret.emplace_back(el.key(), el.value().get<std::string>());
      }
      return ret;
    } catch (...) {}
  }

  return {};
}
void Locales::loadMap(std::string_view path) {
  m_currentPath = path;
  locales = load(path);
}
bool Locales::serialize(const std::string_view path) {
  std::ofstream file(path.data());
  try {
    if (file.is_open()) {
      nlohmann::ordered_json data;

      for (const auto& pair : locales) {
        data[pair.first] = pair.second;
      }

      file << data.dump(4);
      return true;
    }
  } catch (...) {}
  return false;
}
void Locales::saveCurrentLocale() { serialize(m_currentPath); }


code:
#pragma once

#include <nlohmann/json.hpp>

class Locales final {
public:
  friend void to_json(nlohmann::ordered_json& j, const std::pair<std::string, std::string>& templ);
  friend void from_json(const nlohmann::ordered_json& j, std::pair<std::string, std::string>& templ);

  std::vector<std::pair<std::string, std::string>> load(std::string_view path);
  void loadMap(std::string_view path);
  bool serialize(std::string_view path);
  void saveCurrentLocale();

  std::vector<std::pair<std::string, std::string>> locales;

  std::string m_currentPath;
};
void to_json(nlohmann::ordered_json& j, const std::pair<std::string, std::string>& templ);
void from_json(const nlohmann::ordered_json& j, std::pair<std::string, std::string>& templ);


code:
#include "Log.hpp"

#include <spdlog/common.h>
#include <spdlog/logger.h>
#include <spdlog/sinks/basic_file_sink.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/spdlog.h>

#include <memory>
#include <vector>

namespace RPGM {

Log::Log() {
  std::vector<spdlog::sink_ptr> log_sinks;

  const spdlog::level::level_enum level{spdlog::level::debug};

  log_sinks.emplace_back(std::make_shared<spdlog::sinks::stdout_color_sink_mt>());
  log_sinks.emplace_back(std::make_shared<spdlog::sinks::basic_file_sink_mt>("database.log", true));

  log_sinks[0]->set_pattern("%^[%T] %n(%l): %v%$");
  log_sinks[1]->set_pattern("[%T] [%l] %n(%l): %v");

  m_logger = std::make_shared<spdlog::logger>("RPGM", begin(log_sinks), end(log_sinks));
  spdlog::register_logger(m_logger);
  spdlog::set_default_logger(m_logger);
  m_logger->set_level(level);
  m_logger->flush_on(level);
}

} // namespace RPGM


code:
#pragma once

#include <spdlog/fmt/ostr.h>
#include <spdlog/spdlog.h>

#include <memory>

namespace RPGM {

class Log {
public:
  Log(const Log&) = delete;
  Log(const Log&&) = delete;
  Log& operator=(const Log&) = delete;
  Log& operator=(const Log&&) = delete;
  ~Log() = default;

  static std::shared_ptr<spdlog::logger>& logger() { return get().m_logger; }

private:
  // The constructor shall not be deleted but used to bootstrap the logger. Ignoring
  // the lint warning is ignoring doing `Log() = delete`.
  // NOLINTNEXTLINE
  Log();

  static Log& get() {
    static Log instance{};
    return instance;
  }

  std::shared_ptr<spdlog::logger> m_logger;
};

} // namespace RPGM

#ifndef RPGM_DEACTIVATE_LOGGING

#if DEBUG
#define RPGM_TRACE(...) ::RPGM::Log::logger()->trace(__VA_ARGS__)
#define RPGM_DEBUG(...) ::RPGM::Log::logger()->debug(__VA_ARGS__)
#else
#define RPGM_TRACE(...)
#define RPGM_DEBUG(...)
#endif

#define RPGM_INFO(...) ::RPGM::Log::logger()->info(__VA_ARGS__)
#define RPGM_WARN(...) ::RPGM::Log::logger()->warn(__VA_ARGS__)
#define RPGM_ERROR(...) ::RPGM::Log::logger()->error(__VA_ARGS__)
#define RPGM_FATAL(...) ::RPGM::Log::logger()->fatal(__VA_ARGS__)

#else

#define RPGM_TRACE(...)
#define RPGM_DEBUG(...)
#define RPGM_INFO(...)
#define RPGM_WARN(...)
#define RPGM_ERROR(...)
#define RPGM_FATAL(...)

#endif