diff --git a/src/NosCore.Data/Enumerations/I18N/LanguageKey.cs b/src/NosCore.Data/Enumerations/I18N/LanguageKey.cs index db4195236..b14137842 100644 --- a/src/NosCore.Data/Enumerations/I18N/LanguageKey.cs +++ b/src/NosCore.Data/Enumerations/I18N/LanguageKey.cs @@ -65,6 +65,7 @@ public enum LogLanguageKey ITEMS_PARSED, MAPS_PARSED, PORTALS_PARSED, + TIMESPACES_PARSED, MAPS_LOADED, NO_MAP, MAPMONSTERS_LOADED, diff --git a/src/NosCore.Data/Resource/LocalizedResources.cs.resx b/src/NosCore.Data/Resource/LocalizedResources.cs.resx index 00027c8b6..476317870 100644 --- a/src/NosCore.Data/Resource/LocalizedResources.cs.resx +++ b/src/NosCore.Data/Resource/LocalizedResources.cs.resx @@ -530,4 +530,7 @@ Neznámý typ vylepšení: {0} + + Načteno skriptovaných instancí: {0}! + \ No newline at end of file diff --git a/src/NosCore.Data/Resource/LocalizedResources.de.resx b/src/NosCore.Data/Resource/LocalizedResources.de.resx index 841cf7ae7..896d7b45c 100644 --- a/src/NosCore.Data/Resource/LocalizedResources.de.resx +++ b/src/NosCore.Data/Resource/LocalizedResources.de.resx @@ -553,4 +553,7 @@ Unbekannter Aufrüstungstyp: {0} + + {0} Skript-Instanzen geladen! + \ No newline at end of file diff --git a/src/NosCore.Data/Resource/LocalizedResources.es.resx b/src/NosCore.Data/Resource/LocalizedResources.es.resx index 6f761c154..29c9f4f95 100644 --- a/src/NosCore.Data/Resource/LocalizedResources.es.resx +++ b/src/NosCore.Data/Resource/LocalizedResources.es.resx @@ -457,4 +457,7 @@ Tipo de mejora no manejado: {0} + + ¡{0} instancias de script analizadas! + \ No newline at end of file diff --git a/src/NosCore.Data/Resource/LocalizedResources.fr.resx b/src/NosCore.Data/Resource/LocalizedResources.fr.resx index f06f3fbf4..29acf6fac 100644 --- a/src/NosCore.Data/Resource/LocalizedResources.fr.resx +++ b/src/NosCore.Data/Resource/LocalizedResources.fr.resx @@ -528,4 +528,7 @@ Type d'amélioration non géré: {0} + + {0} instances scriptées analysées ! + \ No newline at end of file diff --git a/src/NosCore.Data/Resource/LocalizedResources.it.resx b/src/NosCore.Data/Resource/LocalizedResources.it.resx index cc13b8d36..d9e3a2fa5 100644 --- a/src/NosCore.Data/Resource/LocalizedResources.it.resx +++ b/src/NosCore.Data/Resource/LocalizedResources.it.resx @@ -574,4 +574,7 @@ Tipo di potenziamento non gestito: {0} + + {0} istanze scriptate caricate! + diff --git a/src/NosCore.Data/Resource/LocalizedResources.pl.resx b/src/NosCore.Data/Resource/LocalizedResources.pl.resx index 13c4dbcac..79c77f98a 100644 --- a/src/NosCore.Data/Resource/LocalizedResources.pl.resx +++ b/src/NosCore.Data/Resource/LocalizedResources.pl.resx @@ -480,4 +480,7 @@ Nieobsługiwany typ ulepszenia: {0} + + Wczytano {0} instancji skryptowanych! + \ No newline at end of file diff --git a/src/NosCore.Data/Resource/LocalizedResources.resx b/src/NosCore.Data/Resource/LocalizedResources.resx index d8dc46311..e42167817 100644 --- a/src/NosCore.Data/Resource/LocalizedResources.resx +++ b/src/NosCore.Data/Resource/LocalizedResources.resx @@ -604,4 +604,7 @@ Unhandled upgrade type: {0} + + {0} Scripted Instances Parsed! + \ No newline at end of file diff --git a/src/NosCore.Data/Resource/LocalizedResources.ru.resx b/src/NosCore.Data/Resource/LocalizedResources.ru.resx index c62a7e857..fc7898cd9 100644 --- a/src/NosCore.Data/Resource/LocalizedResources.ru.resx +++ b/src/NosCore.Data/Resource/LocalizedResources.ru.resx @@ -555,4 +555,7 @@ Неизвестный тип улучшения: {0} + + Загружено скриптовых инстансов: {0}! + \ No newline at end of file diff --git a/src/NosCore.Data/Resource/LocalizedResources.tr.resx b/src/NosCore.Data/Resource/LocalizedResources.tr.resx index 9b86778b2..615e4258b 100644 --- a/src/NosCore.Data/Resource/LocalizedResources.tr.resx +++ b/src/NosCore.Data/Resource/LocalizedResources.tr.resx @@ -546,4 +546,7 @@ Bilinmeyen yükseltme türü: {0} + + {0} betikli örnek yüklendi! + \ No newline at end of file diff --git a/src/NosCore.Database/Entities/ScriptedInstance.cs b/src/NosCore.Database/Entities/ScriptedInstance.cs index 191ec566e..9da5e99f5 100644 --- a/src/NosCore.Database/Entities/ScriptedInstance.cs +++ b/src/NosCore.Database/Entities/ScriptedInstance.cs @@ -4,13 +4,16 @@ // |_|\__|\__/ |___/ \__/\__/|_|_\___| // +using NosCore.Data.DataAttributes; +using NosCore.Data.Enumerations.I18N; using NosCore.Data.Enumerations.Interaction; using NosCore.Database.Entities.Base; using System.ComponentModel.DataAnnotations; namespace NosCore.Database.Entities { - public class ScriptedInstance : IEntity + [StaticMetaData(LoadedMessage = LogLanguageKey.TIMESPACES_PARSED)] + public class ScriptedInstance : IStaticEntity { public virtual Map Map { get; set; } = null!; @@ -29,5 +32,11 @@ public class ScriptedInstance : IEntity public short ScriptedInstanceId { get; set; } public ScriptedInstanceType Type { get; set; } + + public byte LevelMinimum { get; set; } + + public byte LevelMaximum { get; set; } + + public bool IsHeroic { get; set; } } } diff --git a/src/NosCore.Database/Hosting/PersistenceModule.cs b/src/NosCore.Database/Hosting/PersistenceModule.cs index 07eba7d3f..4aed2a6a0 100644 --- a/src/NosCore.Database/Hosting/PersistenceModule.cs +++ b/src/NosCore.Database/Hosting/PersistenceModule.cs @@ -73,7 +73,6 @@ protected override void Load(ContainerBuilder builder) // health-check scopes, etc.) can plan handler construction. The runtime IServiceProvider // is still backed by Autofac via AutofacServiceProviderFactory, so resolution semantics // are unchanged — this is a visibility shim, not a second source of truth. - // // Note: we deliberately do NOT mirror the open IDao facet here. PersistenceModule.Load // registers each Dao as both IDao and IDao in Autofac. If we // mirror the IDao facet too, Populate(services) reflows it into Autofac as a SECOND @@ -111,7 +110,7 @@ public static IEnumerable DiscoverDaoMappings() foreach (var dto in assemblyDto.Where(p => typeof(IDto).IsAssignableFrom(p) && - (!p.Name.Contains("InstanceDto") || p.Name.Contains("Inventory")) && p.IsClass)) + !typeof(IItemInstanceDto).IsAssignableFrom(p) && p.IsClass)) { var db = assemblyDb.FirstOrDefault(tgo => string.Compare(dto.Name, $"{tgo.Name}Dto", StringComparison.OrdinalIgnoreCase) == 0); diff --git a/src/NosCore.Database/Migrations/20260822232419_AddScriptedInstanceEntryDetails.Designer.cs b/src/NosCore.Database/Migrations/20260822232419_AddScriptedInstanceEntryDetails.Designer.cs new file mode 100644 index 000000000..a6a7fc071 --- /dev/null +++ b/src/NosCore.Database/Migrations/20260822232419_AddScriptedInstanceEntryDetails.Designer.cs @@ -0,0 +1,4160 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using NodaTime; +using NosCore.Database; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace NosCore.Database.Migrations +{ + [DbContext(typeof(NosCoreContext))] + [Migration("20260822232419_AddScriptedInstanceEntryDetails")] + partial class AddScriptedInstanceEntryDetails + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.11") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "audit_log_type", new[] { "account_creation", "character_creation", "email_update" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "authority_type", new[] { "user", "moderator", "game_master", "administrator", "root", "closed", "banned", "unconfirmed" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "character_class_type", new[] { "adventurer", "swordsman", "archer", "mage", "martial_artist" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "character_relation_type", new[] { "friend", "hidden_spouse", "spouse", "blocked" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "character_state", new[] { "active", "inactive" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "element_type", new[] { "neutral", "fire", "water", "light", "dark" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "equipment_type", new[] { "main_weapon", "armor", "hat", "gloves", "boots", "secondary_weapon", "necklace", "ring", "bracelet", "mask", "fairy", "amulet", "sp", "costume_suit", "costume_hat", "weapon_skin", "wing_skin" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "family_authority", new[] { "head", "assistant", "manager", "member" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "family_authority_type", new[] { "none", "put", "all" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "family_log_type", new[] { "daily_message", "raid_won", "rainbow_battle", "family_xp", "family_level_up", "level_up", "item_upgraded", "right_changed", "authority_changed", "family_managed", "user_managed", "ware_house_added", "ware_house_removed" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "family_member_rank", new[] { "nothing", "old_uncle", "old_aunt", "father", "mother", "uncle", "aunt", "brother", "sister", "spouse", "brother2", "sister2", "old_son", "old_daugter", "middle_son", "middle_daughter", "young_son", "young_daugter", "old_little_son", "old_little_daughter", "little_son", "little_daughter", "middle_little_son", "middle_little_daugter" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "gender_type", new[] { "male", "female" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "hair_color_type", new[] { "dark_purple", "yellow", "blue", "purple", "orange", "brown", "green", "dark_grey", "light_blue", "pink_red", "light_yellow", "light_pink", "light_green", "light_grey", "sky_blue", "black", "dark_orange", "dark_orange_variant2", "dark_orange_variant3", "dark_orange_variant4", "dark_orange_variant5", "dark_orange_variant6", "light_orange", "light_light_orange", "light_light_light_orange", "light_light_light_light_orange", "super_light_orange", "dark_yellow", "light_light_yellow", "kaki_yellow", "super_light_yellow", "super_light_yellow2", "super_light_yellow3", "little_dark_yellow", "yellow_variant", "yellow_variant1", "yellow_variant2", "yellow_variant3", "yellow_variant4", "yellow_variant5", "yellow_variant6", "yellow_variant7", "yellow_variant8", "yellow_variant9", "green_variant", "green_variant1", "dark_green_variant", "green_more_dark_variant", "green_variant2", "green_variant3", "green_variant4", "green_variant5", "green_variant6", "green_variant7", "green_variant8", "green_variant9", "green_variant10", "green_variant11", "green_variant12", "green_variant13", "green_variant14", "green_variant15", "green_variant16", "green_variant17", "green_variant18", "green_variant19", "green_variant20", "light_blue_variant1", "light_blue_variant2", "light_blue_variant3", "light_blue_variant4", "light_blue_variant5", "light_blue_variant6", "light_blue_variant7", "light_blue_variant8", "light_blue_variant9", "light_blue_variant10", "light_blue_variant11", "light_blue_variant12", "light_blue_variant13", "dark_black", "light_blue_variant14", "light_blue_variant15", "light_blue_variant16", "light_blue_variant17", "blue_variant", "blue_variant_dark", "blue_variant_dark_dark", "blue_variant_dark_dark2", "flash_blue", "flash_blue_dark", "flash_blue_dark2", "flash_blue_dark3", "flash_blue_dark4", "flash_blue_dark5", "flash_blue_dark6", "flash_blue_dark7", "flash_blue_dark8", "flash_blue_dark9", "white", "flash_blue_dark10", "flash_blue1", "flash_blue2", "flash_blue3", "flash_blue4", "flash_blue5", "flash_purple", "flash_light_purple", "flash_light_purple2", "flash_light_purple3", "flash_light_purple4", "flash_light_purple5", "light_purple", "purple_variant1", "purple_variant2", "purple_variant3", "purple_variant4", "purple_variant5", "purple_variant6", "purple_variant7", "purple_variant8", "purple_variant9", "purple_variant10", "purple_variant11", "purple_variant12", "purple_variant13", "purple_variant14", "purple_variant15" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "hair_style_type", new[] { "hair_style_a", "hair_style_b", "hair_style_c", "hair_style_d", "no_hair" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "item_effect_type", new[] { "no_effect", "teleport", "apply_hair_die", "apply_hair_style", "speaker", "marriage_proposal", "undefined", "sp_charger", "mate_capture", "dropped_sp_recharger", "premium_sp_recharger", "crafted_sp_recharger", "specialist_medal", "apply_skin_partner", "change_gender", "point_initialisation", "sealed_tarot_card", "tarot_card", "red_amulet", "blue_amulet", "reinforcement_amulet", "heroic", "random_heroic", "attack_amulet", "defense_amulet", "speed_booster", "box_effect", "vehicle", "gold_nos_merchant_upgrade", "silver_nos_merchant_upgrade", "inventory_upgrade", "pet_space_upgrade", "pet_basket_upgrade", "pet_backpack_upgrade", "inventory_ticket_upgrade", "buff_potions", "marriage_separation" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "item_type", new[] { "weapon", "armor", "fashion", "jewelery", "specialist", "box", "shell", "main", "upgrade", "production", "map", "special", "potion", "event", "title", "quest1", "sell", "food", "snack", "magical", "part", "teacher", "ammo", "quest2", "house", "garden", "minigame", "terrace", "miniland_theme" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "mate_type", new[] { "partner", "pet" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "miniland_state", new[] { "open", "private", "lock" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "monster_type", new[] { "unknown", "partner", "npc", "well", "portal", "boss", "elite", "peapod", "special", "gem_space_time" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "noscore_pocket_type", new[] { "equipment", "main", "etc", "miniland", "specialist", "costume", "wear", "mount", "raid" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "penalty_type", new[] { "muted", "banned", "block_exp", "block_f_exp", "block_rep", "warning" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "portal_type", new[] { "ts_normal", "closed", "open", "miniland", "ts_end", "ts_end_closed", "exit", "exit_closed", "raid", "effect", "blue_raid", "dark_raid", "time_space", "shop_teleport", "map_portal" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "quest_type", new[] { "hunt", "special_collect", "collect_in_raid", "brings", "capture_without_getting_the_monster", "capture", "times_space", "product", "number_of_kill", "target_reput", "ts_point", "dialog1", "collect_in_ts", "required", "wear", "needed", "collect", "transmit_gold", "go_to", "collect_map_entity", "use", "dialog2", "un_know", "inspect", "win_raid", "flower_quest" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "region_type", new[] { "en", "de", "fr", "it", "pl", "es", "ru", "cs", "tr" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "scripted_instance_type", new[] { "time_space", "raid", "raid_act4" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "static_bonus_type", new[] { "bazaar_medal_gold", "bazaar_medal_silver", "back_pack", "pet_basket", "pet_back_pack", "inventory_ticket_upgrade" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "teleporter_type", new[] { "teleporter", "teleporter_on_map" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "warehouse_type", new[] { "warehouse", "family_ware_house", "pet_warehouse" }); + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("NosCore.Database.Entities.Account", b => + { + b.Property("AccountId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AccountId")); + + b.Property("Authority") + .HasColumnType("smallint"); + + b.Property("BankMoney") + .HasColumnType("bigint"); + + b.Property("Email") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ItemShopMoney") + .HasColumnType("bigint"); + + b.Property("Language") + .HasColumnType("integer"); + + b.Property("MfaSecret") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("NewAuthPassword") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("NewAuthSalt") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("Password") + .HasMaxLength(255) + .IsUnicode(false) + .HasColumnType("character varying(255)"); + + b.Property("RegistrationIp") + .HasMaxLength(45) + .HasColumnType("character varying(45)"); + + b.Property("VerificationToken") + .HasMaxLength(32) + .HasColumnType("character varying(32)"); + + b.HasKey("AccountId"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("Account"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Act", b => + { + b.Property("ActId") + .HasColumnType("smallint"); + + b.Property("Scene") + .HasColumnType("smallint"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("ActId"); + + b.ToTable("Act"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.ActPart", b => + { + b.Property("ActPartId") + .HasColumnType("smallint"); + + b.Property("ActId") + .HasColumnType("smallint"); + + b.Property("ActPartNumber") + .HasColumnType("smallint"); + + b.Property("MaxTs") + .HasColumnType("smallint"); + + b.HasKey("ActPartId"); + + b.HasIndex("ActId"); + + b.ToTable("ActPart"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.AuditLog", b => + { + b.Property("AuditId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuditLogType") + .HasColumnType("integer"); + + b.Property("TargetId") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("TargetType") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("character varying(32)"); + + b.Property("Time") + .HasColumnType("timestamp with time zone"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("AuditId"); + + b.ToTable("AuditLog"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.BCard", b => + { + b.Property("BCardId") + .ValueGeneratedOnAdd() + .HasColumnType("smallint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BCardId")); + + b.Property("CardId") + .HasColumnType("smallint"); + + b.Property("CastType") + .HasColumnType("smallint"); + + b.Property("FirstData") + .HasColumnType("integer"); + + b.Property("IsLevelDivided") + .HasColumnType("boolean"); + + b.Property("IsLevelScaled") + .HasColumnType("boolean"); + + b.Property("ItemVNum") + .HasColumnType("smallint"); + + b.Property("NpcMonsterVNum") + .HasColumnType("smallint"); + + b.Property("SecondData") + .HasColumnType("integer"); + + b.Property("SkillVNum") + .HasColumnType("smallint"); + + b.Property("Slot") + .HasColumnType("smallint"); + + b.Property("SubType") + .HasColumnType("smallint"); + + b.Property("ThirdData") + .HasColumnType("integer"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.HasKey("BCardId"); + + b.HasIndex("CardId"); + + b.HasIndex("ItemVNum"); + + b.HasIndex("NpcMonsterVNum"); + + b.HasIndex("SkillVNum"); + + b.ToTable("BCard"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.BazaarItem", b => + { + b.Property("BazaarItemId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BazaarItemId")); + + b.Property("Amount") + .HasColumnType("smallint"); + + b.Property("DateStart") + .HasColumnType("timestamp with time zone"); + + b.Property("Duration") + .HasColumnType("smallint"); + + b.Property("IsPackage") + .HasColumnType("boolean"); + + b.Property("ItemInstanceId") + .HasColumnType("uuid"); + + b.Property("MedalUsed") + .HasColumnType("boolean"); + + b.Property("Price") + .HasColumnType("bigint"); + + b.Property("SellerId") + .HasColumnType("bigint"); + + b.HasKey("BazaarItemId"); + + b.HasIndex("ItemInstanceId"); + + b.HasIndex("SellerId"); + + b.ToTable("BazaarItem"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Card", b => + { + b.Property("CardId") + .HasColumnType("smallint"); + + b.Property("BuffType") + .HasColumnType("smallint"); + + b.Property("Delay") + .HasColumnType("integer"); + + b.Property("Duration") + .HasColumnType("integer"); + + b.Property("EffectId") + .HasColumnType("integer"); + + b.Property("Level") + .HasColumnType("smallint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("Propability") + .HasColumnType("smallint"); + + b.Property("TimeoutBuff") + .HasColumnType("smallint"); + + b.Property("TimeoutBuffChance") + .HasColumnType("smallint"); + + b.HasKey("CardId"); + + b.ToTable("Card"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Character", b => + { + b.Property("CharacterId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CharacterId")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("Act4Dead") + .HasColumnType("integer"); + + b.Property("Act4Kill") + .HasColumnType("integer"); + + b.Property("Act4Points") + .HasColumnType("integer"); + + b.Property("ArenaWinner") + .HasColumnType("integer"); + + b.Property("Biography") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("BuffBlocked") + .HasColumnType("boolean"); + + b.Property("Class") + .HasColumnType("smallint"); + + b.Property("Compliment") + .HasColumnType("smallint"); + + b.Property("CurrentScriptId") + .HasColumnType("uuid"); + + b.Property("Dignity") + .HasColumnType("smallint"); + + b.Property("Elo") + .HasColumnType("integer"); + + b.Property("EmoticonsBlocked") + .HasColumnType("boolean"); + + b.Property("ExchangeBlocked") + .HasColumnType("boolean"); + + b.Property("Faction") + .HasColumnType("smallint"); + + b.Property("FamilyRequestBlocked") + .HasColumnType("boolean"); + + b.Property("FriendRequestBlocked") + .HasColumnType("boolean"); + + b.Property("Gender") + .HasColumnType("smallint"); + + b.Property("Gold") + .HasColumnType("bigint"); + + b.Property("GroupRequestBlocked") + .HasColumnType("boolean"); + + b.Property("HairColor") + .HasColumnType("smallint"); + + b.Property("HairStyle") + .HasColumnType("smallint"); + + b.Property("HeroChatBlocked") + .HasColumnType("boolean"); + + b.Property("HeroLevel") + .HasColumnType("smallint"); + + b.Property("HeroXp") + .HasColumnType("bigint"); + + b.Property("Hp") + .HasColumnType("integer"); + + b.Property("HpBlocked") + .HasColumnType("boolean"); + + b.Property("JobLevel") + .HasColumnType("smallint"); + + b.Property("JobLevelXp") + .HasColumnType("bigint"); + + b.Property("Level") + .HasColumnType("smallint"); + + b.Property("LevelXp") + .HasColumnType("bigint"); + + b.Property("MapId") + .HasColumnType("smallint"); + + b.Property("MapX") + .HasColumnType("smallint"); + + b.Property("MapY") + .HasColumnType("smallint"); + + b.Property("MasterPoints") + .HasColumnType("integer"); + + b.Property("MasterTicket") + .HasColumnType("integer"); + + b.Property("MaxMateCount") + .HasColumnType("smallint"); + + b.Property("MinilandInviteBlocked") + .HasColumnType("boolean"); + + b.Property("MouseAimLock") + .HasColumnType("boolean"); + + b.Property("Mp") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .IsUnicode(false) + .HasColumnType("character varying(255)"); + + b.Property("Prefix") + .HasMaxLength(25) + .HasColumnType("character varying(25)"); + + b.Property("QuickGetUp") + .HasColumnType("boolean"); + + b.Property("RagePoint") + .HasColumnType("bigint"); + + b.Property("Reput") + .HasColumnType("bigint"); + + b.Property("ServerId") + .HasColumnType("smallint"); + + b.Property("ShouldRename") + .HasColumnType("boolean"); + + b.Property("Slot") + .HasColumnType("smallint"); + + b.Property("SpAdditionPoint") + .HasColumnType("integer"); + + b.Property("SpPoint") + .HasColumnType("integer"); + + b.Property("State") + .HasColumnType("smallint"); + + b.Property("TalentLose") + .HasColumnType("integer"); + + b.Property("TalentSurrender") + .HasColumnType("integer"); + + b.Property("TalentWin") + .HasColumnType("integer"); + + b.Property("WhisperBlocked") + .HasColumnType("boolean"); + + b.HasKey("CharacterId"); + + b.HasIndex("AccountId"); + + b.HasIndex("CurrentScriptId"); + + b.HasIndex("MapId"); + + b.ToTable("Character"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.CharacterActPart", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ActPartId") + .HasColumnType("smallint"); + + b.Property("CharacterId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ActPartId"); + + b.HasIndex("CharacterId"); + + b.ToTable("CharacterActPart"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.CharacterQuest", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CharacterId") + .HasColumnType("bigint"); + + b.Property("CompletedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("QuestId") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("CharacterId"); + + b.HasIndex("QuestId"); + + b.ToTable("CharacterQuest"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.CharacterQuestObjective", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CharacterQuestId") + .HasColumnType("uuid"); + + b.Property("Count") + .HasColumnType("integer"); + + b.Property("QuestObjectiveId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("QuestObjectiveId"); + + b.HasIndex("CharacterQuestId", "QuestObjectiveId") + .IsUnique(); + + b.ToTable("CharacterQuestObjective"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.CharacterRelation", b => + { + b.Property("CharacterRelationId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CharacterId") + .HasColumnType("bigint"); + + b.Property("RelatedCharacterId") + .HasColumnType("bigint"); + + b.Property("RelationType") + .HasColumnType("smallint"); + + b.HasKey("CharacterRelationId"); + + b.HasIndex("CharacterId"); + + b.HasIndex("RelatedCharacterId"); + + b.ToTable("CharacterRelation"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.CharacterSkill", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CharacterId") + .HasColumnType("bigint"); + + b.Property("SkillVNum") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("CharacterId"); + + b.HasIndex("SkillVNum"); + + b.ToTable("CharacterSkill"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Combo", b => + { + b.Property("ComboId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ComboId")); + + b.Property("Animation") + .HasColumnType("smallint"); + + b.Property("Effect") + .HasColumnType("smallint"); + + b.Property("Hit") + .HasColumnType("smallint"); + + b.Property("SkillVNum") + .HasColumnType("smallint"); + + b.HasKey("ComboId"); + + b.HasIndex("SkillVNum"); + + b.ToTable("Combo"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Drop", b => + { + b.Property("DropId") + .ValueGeneratedOnAdd() + .HasColumnType("smallint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DropId")); + + b.Property("Amount") + .HasColumnType("integer"); + + b.Property("DropChance") + .HasColumnType("integer"); + + b.Property("MapTypeId") + .HasColumnType("smallint"); + + b.Property("MonsterVNum") + .HasColumnType("smallint"); + + b.Property("VNum") + .HasColumnType("smallint"); + + b.HasKey("DropId"); + + b.HasIndex("MapTypeId"); + + b.HasIndex("MonsterVNum"); + + b.HasIndex("VNum"); + + b.ToTable("Drop"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.EquipmentOption", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Level") + .HasColumnType("smallint"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.Property("Value") + .HasColumnType("integer"); + + b.Property("WearableInstanceId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("WearableInstanceId"); + + b.ToTable("EquipmentOption"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Family", b => + { + b.Property("FamilyId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("FamilyId")); + + b.Property("FamilyExperience") + .HasColumnType("integer"); + + b.Property("FamilyFaction") + .HasColumnType("smallint"); + + b.Property("FamilyHeadGender") + .HasColumnType("smallint"); + + b.Property("FamilyLevel") + .HasColumnType("smallint"); + + b.Property("FamilyMessage") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ManagerAuthorityType") + .HasColumnType("integer"); + + b.Property("ManagerCanGetHistory") + .HasColumnType("boolean"); + + b.Property("ManagerCanInvite") + .HasColumnType("boolean"); + + b.Property("ManagerCanNotice") + .HasColumnType("boolean"); + + b.Property("ManagerCanShout") + .HasColumnType("boolean"); + + b.Property("MaxSize") + .HasColumnType("smallint"); + + b.Property("MemberAuthorityType") + .HasColumnType("integer"); + + b.Property("MemberCanGetHistory") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("WarehouseSize") + .HasColumnType("smallint"); + + b.HasKey("FamilyId"); + + b.ToTable("Family"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.FamilyCharacter", b => + { + b.Property("FamilyCharacterId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("FamilyCharacterId")); + + b.Property("Authority") + .HasColumnType("smallint"); + + b.Property("CharacterId") + .HasColumnType("bigint"); + + b.Property("DailyMessage") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("Experience") + .HasColumnType("integer"); + + b.Property("FamilyId") + .HasColumnType("bigint"); + + b.Property("Rank") + .HasColumnType("smallint"); + + b.HasKey("FamilyCharacterId"); + + b.HasIndex("CharacterId"); + + b.HasIndex("FamilyId"); + + b.ToTable("FamilyCharacter"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.FamilyLog", b => + { + b.Property("FamilyLogId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("FamilyLogId")); + + b.Property("FamilyId") + .HasColumnType("bigint"); + + b.Property("FamilyLogData") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("FamilyLogType") + .HasColumnType("smallint"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone"); + + b.HasKey("FamilyLogId"); + + b.HasIndex("FamilyId"); + + b.ToTable("FamilyLog"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.I18NActDesc", b => + { + b.Property("I18NActDescId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("I18NActDescId")); + + b.Property("Key") + .IsRequired() + .HasColumnType("text"); + + b.Property("RegionType") + .HasColumnType("integer"); + + b.Property("Text") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("I18NActDescId"); + + b.HasIndex("Key", "RegionType") + .IsUnique(); + + b.ToTable("I18NActDesc"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.I18NBCard", b => + { + b.Property("I18NbCardId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("I18NbCardId")); + + b.Property("Key") + .IsRequired() + .HasColumnType("text"); + + b.Property("RegionType") + .HasColumnType("integer"); + + b.Property("Text") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("I18NbCardId"); + + b.HasIndex("Key", "RegionType") + .IsUnique(); + + b.ToTable("I18NBCard"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.I18NCard", b => + { + b.Property("I18NCardId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("I18NCardId")); + + b.Property("Key") + .IsRequired() + .HasColumnType("text"); + + b.Property("RegionType") + .HasColumnType("integer"); + + b.Property("Text") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("I18NCardId"); + + b.HasIndex("Key", "RegionType") + .IsUnique(); + + b.ToTable("I18NCard"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.I18NItem", b => + { + b.Property("I18NItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("I18NItemId")); + + b.Property("Key") + .IsRequired() + .HasColumnType("text"); + + b.Property("RegionType") + .HasColumnType("integer"); + + b.Property("Text") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("I18NItemId"); + + b.HasIndex("Key", "RegionType") + .IsUnique(); + + b.ToTable("I18NItem"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.I18NMapIdData", b => + { + b.Property("I18NMapIdDataId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("I18NMapIdDataId")); + + b.Property("Key") + .IsRequired() + .HasColumnType("text"); + + b.Property("RegionType") + .HasColumnType("integer"); + + b.Property("Text") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("I18NMapIdDataId"); + + b.HasIndex("Key", "RegionType") + .IsUnique(); + + b.ToTable("I18NMapIdData"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.I18NMapPointData", b => + { + b.Property("I18NMapPointDataId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("I18NMapPointDataId")); + + b.Property("Key") + .IsRequired() + .HasColumnType("text"); + + b.Property("RegionType") + .HasColumnType("integer"); + + b.Property("Text") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("I18NMapPointDataId"); + + b.HasIndex("Key", "RegionType") + .IsUnique(); + + b.ToTable("I18NMapPointData"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.I18NNpcMonster", b => + { + b.Property("I18NNpcMonsterId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("I18NNpcMonsterId")); + + b.Property("Key") + .IsRequired() + .HasColumnType("text"); + + b.Property("RegionType") + .HasColumnType("integer"); + + b.Property("Text") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("I18NNpcMonsterId"); + + b.HasIndex("Key", "RegionType") + .IsUnique(); + + b.ToTable("I18NNpcMonster"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.I18NNpcMonsterTalk", b => + { + b.Property("I18NNpcMonsterTalkId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("I18NNpcMonsterTalkId")); + + b.Property("Key") + .IsRequired() + .HasColumnType("text"); + + b.Property("RegionType") + .HasColumnType("integer"); + + b.Property("Text") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("I18NNpcMonsterTalkId"); + + b.HasIndex("Key", "RegionType") + .IsUnique(); + + b.ToTable("I18NNpcMonsterTalk"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.I18NQuest", b => + { + b.Property("I18NQuestId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("I18NQuestId")); + + b.Property("Key") + .IsRequired() + .HasColumnType("text"); + + b.Property("RegionType") + .HasColumnType("integer"); + + b.Property("Text") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("I18NQuestId"); + + b.HasIndex("Key", "RegionType") + .IsUnique(); + + b.ToTable("I18NQuest"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.I18NSkill", b => + { + b.Property("I18NSkillId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("I18NSkillId")); + + b.Property("Key") + .IsRequired() + .HasColumnType("text"); + + b.Property("RegionType") + .HasColumnType("integer"); + + b.Property("Text") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("I18NSkillId"); + + b.HasIndex("Key", "RegionType") + .IsUnique(); + + b.ToTable("I18NSkill"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.InventoryItemInstance", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CharacterId") + .HasColumnType("bigint"); + + b.Property("ItemInstanceId") + .HasColumnType("uuid"); + + b.Property("Slot") + .HasColumnType("smallint"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("ItemInstanceId"); + + b.HasIndex("CharacterId", "Slot", "Type") + .IsUnique(); + + b.ToTable("InventoryItemInstance"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Item", b => + { + b.Property("VNum") + .HasColumnType("smallint"); + + b.Property("BasicUpgrade") + .HasColumnType("smallint"); + + b.Property("CellonLvl") + .HasColumnType("smallint"); + + b.Property("Class") + .HasColumnType("smallint"); + + b.Property("CloseDefence") + .HasColumnType("smallint"); + + b.Property("Color") + .HasColumnType("smallint"); + + b.Property("Concentrate") + .HasColumnType("smallint"); + + b.Property("CriticalLuckRate") + .HasColumnType("smallint"); + + b.Property("CriticalRate") + .HasColumnType("smallint"); + + b.Property("DamageMaximum") + .HasColumnType("smallint"); + + b.Property("DamageMinimum") + .HasColumnType("smallint"); + + b.Property("DarkElement") + .HasColumnType("smallint"); + + b.Property("DarkResistance") + .HasColumnType("smallint"); + + b.Property("DefenceDodge") + .HasColumnType("smallint"); + + b.Property("DistanceDefence") + .HasColumnType("smallint"); + + b.Property("DistanceDefenceDodge") + .HasColumnType("smallint"); + + b.Property("Effect") + .HasColumnType("integer"); + + b.Property("EffectValue") + .HasColumnType("integer"); + + b.Property("Element") + .HasColumnType("integer"); + + b.Property("ElementRate") + .HasColumnType("smallint"); + + b.Property("EquipmentSlot") + .HasColumnType("smallint"); + + b.Property("FireElement") + .HasColumnType("smallint"); + + b.Property("FireResistance") + .HasColumnType("smallint"); + + b.Property("Flag1") + .HasColumnType("boolean"); + + b.Property("Flag2") + .HasColumnType("boolean"); + + b.Property("Flag3") + .HasColumnType("boolean"); + + b.Property("Flag4") + .HasColumnType("boolean"); + + b.Property("Flag6") + .HasColumnType("boolean"); + + b.Property("Flag7") + .HasColumnType("boolean"); + + b.Property("Flag8") + .HasColumnType("boolean"); + + b.Property("Flag9") + .HasColumnType("boolean"); + + b.Property("Height") + .HasColumnType("smallint"); + + b.Property("HitRate") + .HasColumnType("smallint"); + + b.Property("Hp") + .HasColumnType("smallint"); + + b.Property("HpRegeneration") + .HasColumnType("smallint"); + + b.Property("IsColored") + .HasColumnType("boolean"); + + b.Property("IsConsumable") + .HasColumnType("boolean"); + + b.Property("IsDroppable") + .HasColumnType("boolean"); + + b.Property("IsHeroic") + .HasColumnType("boolean"); + + b.Property("IsMinilandActionable") + .HasColumnType("boolean"); + + b.Property("IsSoldable") + .HasColumnType("boolean"); + + b.Property("IsTradable") + .HasColumnType("boolean"); + + b.Property("IsWarehouse") + .HasColumnType("boolean"); + + b.Property("ItemSubType") + .HasColumnType("smallint"); + + b.Property("ItemType") + .HasColumnType("smallint"); + + b.Property("ItemValidTime") + .HasColumnType("bigint"); + + b.Property("LevelJobMinimum") + .HasColumnType("smallint"); + + b.Property("LevelMinimum") + .HasColumnType("smallint"); + + b.Property("LightElement") + .HasColumnType("smallint"); + + b.Property("LightResistance") + .HasColumnType("smallint"); + + b.Property("MagicDefence") + .HasColumnType("smallint"); + + b.Property("MaxCellon") + .HasColumnType("smallint"); + + b.Property("MaxCellonLvl") + .HasColumnType("smallint"); + + b.Property("MaxElementRate") + .HasColumnType("smallint"); + + b.Property("MaximumAmmo") + .HasColumnType("smallint"); + + b.Property("MinilandObjectPoint") + .HasColumnType("integer"); + + b.Property("MoreHp") + .HasColumnType("smallint"); + + b.Property("MoreMp") + .HasColumnType("smallint"); + + b.Property("Morph") + .HasColumnType("smallint"); + + b.Property("Mp") + .HasColumnType("smallint"); + + b.Property("MpRegeneration") + .HasColumnType("smallint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("Price") + .HasColumnType("bigint"); + + b.Property("PvpDefence") + .HasColumnType("smallint"); + + b.Property("PvpStrength") + .HasColumnType("smallint"); + + b.Property("ReduceOposantResistance") + .HasColumnType("smallint"); + + b.Property("ReputPrice") + .HasColumnType("bigint"); + + b.Property("ReputationMinimum") + .HasColumnType("smallint"); + + b.Property("RequireBinding") + .HasColumnType("boolean"); + + b.Property("SecondMorph") + .HasColumnType("smallint"); + + b.Property("SecondaryElement") + .HasColumnType("integer"); + + b.Property("Sex") + .HasColumnType("smallint"); + + b.Property("SpType") + .HasColumnType("smallint"); + + b.Property("Speed") + .HasColumnType("smallint"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.Property("WaitDelay") + .HasColumnType("smallint"); + + b.Property("WaterElement") + .HasColumnType("smallint"); + + b.Property("WaterResistance") + .HasColumnType("smallint"); + + b.Property("Width") + .HasColumnType("smallint"); + + b.HasKey("VNum"); + + b.ToTable("Item"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.ItemInstance", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("smallint"); + + b.Property("BoundCharacterId") + .HasColumnType("bigint"); + + b.Property("CharacterId") + .HasColumnType("bigint"); + + b.Property("Design") + .HasColumnType("smallint"); + + b.Property("Discriminator") + .IsRequired() + .HasMaxLength(21) + .HasColumnType("character varying(21)"); + + b.Property("DurabilityPoint") + .HasColumnType("integer"); + + b.Property("ItemDeleteTime") + .HasColumnType("timestamp with time zone"); + + b.Property("ItemVNum") + .HasColumnType("smallint"); + + b.Property("Rare") + .HasColumnType("smallint"); + + b.Property("Upgrade") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("BoundCharacterId"); + + b.HasIndex("ItemVNum"); + + b.ToTable("ItemInstance"); + + b.HasDiscriminator("Discriminator").HasValue("ItemInstance"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Mail", b => + { + b.Property("MailId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MailId")); + + b.Property("Armor") + .HasColumnType("smallint"); + + b.Property("CostumeHat") + .HasColumnType("smallint"); + + b.Property("CostumeSuit") + .HasColumnType("smallint"); + + b.Property("Date") + .HasColumnType("timestamp with time zone"); + + b.Property("Fairy") + .HasColumnType("smallint"); + + b.Property("Hat") + .HasColumnType("smallint"); + + b.Property("IsOpened") + .HasColumnType("boolean"); + + b.Property("IsSenderCopy") + .HasColumnType("boolean"); + + b.Property("ItemInstanceId") + .HasColumnType("uuid"); + + b.Property("MainWeapon") + .HasColumnType("smallint"); + + b.Property("Mask") + .HasColumnType("smallint"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ReceiverId") + .HasColumnType("bigint"); + + b.Property("SecondaryWeapon") + .HasColumnType("smallint"); + + b.Property("SenderCharacterClass") + .HasColumnType("smallint"); + + b.Property("SenderGender") + .HasColumnType("smallint"); + + b.Property("SenderHairColor") + .HasColumnType("smallint"); + + b.Property("SenderHairStyle") + .HasColumnType("smallint"); + + b.Property("SenderId") + .HasColumnType("bigint"); + + b.Property("SenderMorphId") + .HasColumnType("smallint"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("WeaponSkin") + .HasColumnType("smallint"); + + b.Property("WingSkin") + .HasColumnType("smallint"); + + b.HasKey("MailId"); + + b.HasIndex("ItemInstanceId"); + + b.HasIndex("ReceiverId"); + + b.HasIndex("SenderId"); + + b.ToTable("Mail"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Map", b => + { + b.Property("MapId") + .HasColumnType("smallint"); + + b.Property("Data") + .IsRequired() + .HasColumnType("bytea"); + + b.Property("Music") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ShopAllowed") + .HasColumnType("boolean"); + + b.HasKey("MapId"); + + b.ToTable("Map"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.MapMonster", b => + { + b.Property("MapMonsterId") + .HasColumnType("integer"); + + b.Property("Direction") + .HasColumnType("smallint"); + + b.Property("IsDisabled") + .HasColumnType("boolean"); + + b.Property("MapId") + .HasColumnType("smallint"); + + b.Property("MapX") + .HasColumnType("smallint"); + + b.Property("MapY") + .HasColumnType("smallint"); + + b.Property("VNum") + .HasColumnType("smallint"); + + b.HasKey("MapMonsterId"); + + b.HasIndex("MapId"); + + b.HasIndex("VNum"); + + b.ToTable("MapMonster"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.MapNpc", b => + { + b.Property("MapNpcId") + .HasColumnType("integer"); + + b.Property("Dialog") + .HasColumnType("smallint"); + + b.Property("Direction") + .HasColumnType("smallint"); + + b.Property("Effect") + .HasColumnType("smallint"); + + b.Property("EffectDelay") + .HasColumnType("smallint"); + + b.Property("IsDisabled") + .HasColumnType("boolean"); + + b.Property("IsMoving") + .HasColumnType("boolean"); + + b.Property("IsSitting") + .HasColumnType("boolean"); + + b.Property("MapId") + .HasColumnType("smallint"); + + b.Property("MapX") + .HasColumnType("smallint"); + + b.Property("MapY") + .HasColumnType("smallint"); + + b.Property("VNum") + .HasColumnType("smallint"); + + b.HasKey("MapNpcId"); + + b.HasIndex("Dialog"); + + b.HasIndex("MapId"); + + b.HasIndex("VNum"); + + b.ToTable("MapNpc"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.MapType", b => + { + b.Property("MapTypeId") + .HasColumnType("smallint"); + + b.Property("MapTypeName") + .IsRequired() + .HasColumnType("text"); + + b.Property("PotionDelay") + .HasColumnType("smallint"); + + b.Property("RespawnMapTypeId") + .HasColumnType("bigint"); + + b.Property("ReturnMapTypeId") + .HasColumnType("bigint"); + + b.HasKey("MapTypeId"); + + b.HasIndex("RespawnMapTypeId"); + + b.HasIndex("ReturnMapTypeId"); + + b.ToTable("MapType"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.MapTypeMap", b => + { + b.Property("MapTypeMapId") + .ValueGeneratedOnAdd() + .HasColumnType("smallint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MapTypeMapId")); + + b.Property("MapId") + .HasColumnType("smallint"); + + b.Property("MapTypeId") + .HasColumnType("smallint"); + + b.HasKey("MapTypeMapId"); + + b.HasIndex("MapTypeId"); + + b.HasIndex("MapId", "MapTypeId") + .IsUnique(); + + b.ToTable("MapTypeMap"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Mate", b => + { + b.Property("MateId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MateId")); + + b.Property("Attack") + .HasColumnType("smallint"); + + b.Property("CanPickUp") + .HasColumnType("boolean"); + + b.Property("CharacterId") + .HasColumnType("bigint"); + + b.Property("Defence") + .HasColumnType("smallint"); + + b.Property("Direction") + .HasColumnType("smallint"); + + b.Property("Experience") + .HasColumnType("bigint"); + + b.Property("Hp") + .HasColumnType("integer"); + + b.Property("IsSummonable") + .HasColumnType("boolean"); + + b.Property("IsTeamMember") + .HasColumnType("boolean"); + + b.Property("Level") + .HasColumnType("smallint"); + + b.Property("Loyalty") + .HasColumnType("smallint"); + + b.Property("MapX") + .HasColumnType("smallint"); + + b.Property("MapY") + .HasColumnType("smallint"); + + b.Property("MateType") + .HasColumnType("smallint"); + + b.Property("Mp") + .HasColumnType("integer"); + + b.Property("Name") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("Skin") + .HasColumnType("smallint"); + + b.Property("VNum") + .HasColumnType("smallint"); + + b.HasKey("MateId"); + + b.HasIndex("CharacterId"); + + b.HasIndex("VNum"); + + b.ToTable("Mate"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Miniland", b => + { + b.Property("MinilandId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DailyVisitCount") + .HasColumnType("integer"); + + b.Property("MinilandMessage") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("MinilandPoint") + .HasColumnType("bigint"); + + b.Property("OwnerId") + .HasColumnType("bigint"); + + b.Property("State") + .HasColumnType("smallint"); + + b.Property("VisitCount") + .HasColumnType("integer"); + + b.Property("WelcomeMusicInfo") + .HasColumnType("smallint"); + + b.HasKey("MinilandId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Miniland"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.MinilandObject", b => + { + b.Property("MinilandObjectId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("InventoryItemInstanceId") + .HasColumnType("uuid"); + + b.Property("Level1BoxAmount") + .HasColumnType("smallint"); + + b.Property("Level2BoxAmount") + .HasColumnType("smallint"); + + b.Property("Level3BoxAmount") + .HasColumnType("smallint"); + + b.Property("Level4BoxAmount") + .HasColumnType("smallint"); + + b.Property("Level5BoxAmount") + .HasColumnType("smallint"); + + b.Property("MapX") + .HasColumnType("smallint"); + + b.Property("MapY") + .HasColumnType("smallint"); + + b.HasKey("MinilandObjectId"); + + b.HasIndex("InventoryItemInstanceId"); + + b.ToTable("MinilandObject"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.NpcMonster", b => + { + b.Property("NpcMonsterVNum") + .HasColumnType("smallint"); + + b.Property("AlwaysActive") + .HasColumnType("boolean"); + + b.Property("AmountRequired") + .HasColumnType("smallint"); + + b.Property("AttackClass") + .HasColumnType("smallint"); + + b.Property("AttackUpgrade") + .HasColumnType("smallint"); + + b.Property("BasicArea") + .HasColumnType("smallint"); + + b.Property("BasicCooldown") + .HasColumnType("smallint"); + + b.Property("BasicHitChance") + .HasColumnType("smallint"); + + b.Property("BasicRange") + .HasColumnType("smallint"); + + b.Property("BasicSkill") + .HasColumnType("smallint"); + + b.Property("CModeVNum") + .HasColumnType("smallint"); + + b.Property("CanCatch") + .HasColumnType("boolean"); + + b.Property("CanCollect") + .HasColumnType("boolean"); + + b.Property("CanOnlyBeDmgedByJajamaruLastSkill") + .HasColumnType("boolean"); + + b.Property("CanWalk") + .HasColumnType("boolean"); + + b.Property("CantDebuff") + .HasColumnType("boolean"); + + b.Property("CantTargetInfo") + .HasColumnType("boolean"); + + b.Property("CantVoke") + .HasColumnType("boolean"); + + b.Property("CellMinRange") + .HasColumnType("smallint"); + + b.Property("CellSize") + .HasColumnType("smallint"); + + b.Property("CloseDefence") + .HasColumnType("smallint"); + + b.Property("Concentrate") + .HasColumnType("smallint"); + + b.Property("CriticalChance") + .HasColumnType("smallint"); + + b.Property("CriticalRate") + .HasColumnType("smallint"); + + b.Property("DamageMaximum") + .HasColumnType("smallint"); + + b.Property("DamageMinimum") + .HasColumnType("smallint"); + + b.Property("DarkResistance") + .HasColumnType("smallint"); + + b.Property("DashSpeed") + .HasColumnType("smallint"); + + b.Property("DefenceDodge") + .HasColumnType("smallint"); + + b.Property("DefenceUpgrade") + .HasColumnType("smallint"); + + b.Property("DisappearAfterHitting") + .HasColumnType("boolean"); + + b.Property("DisappearAfterSeconds") + .HasColumnType("boolean"); + + b.Property("DisappearAfterSecondsMana") + .HasColumnType("boolean"); + + b.Property("DistanceDefence") + .HasColumnType("smallint"); + + b.Property("DistanceDefenceDodge") + .HasColumnType("smallint"); + + b.Property("DontDrainHpAfterSeconds") + .HasColumnType("boolean"); + + b.Property("EffectIdConstantly") + .HasColumnType("smallint"); + + b.Property("EffectIdOnDeath") + .HasColumnType("smallint"); + + b.Property("Element") + .HasColumnType("smallint"); + + b.Property("ElementRate") + .HasColumnType("smallint"); + + b.Property("FireResistance") + .HasColumnType("smallint"); + + b.Property("GiveDamagePercentage") + .HasColumnType("integer"); + + b.Property("GroupAttack") + .HasColumnType("smallint"); + + b.Property("HasDash") + .HasColumnType("boolean"); + + b.Property("HasMode") + .HasColumnType("boolean"); + + b.Property("HeroLevel") + .HasColumnType("smallint"); + + b.Property("HeroXp") + .HasColumnType("integer"); + + b.Property("HpThreshold") + .HasColumnType("smallint"); + + b.Property("IconId") + .HasColumnType("smallint"); + + b.Property("IsHostile") + .HasColumnType("boolean"); + + b.Property("IsPercent") + .HasColumnType("boolean"); + + b.Property("IsPercentileDmg") + .HasColumnType("boolean"); + + b.Property("IsValhallaPartner") + .HasColumnType("boolean"); + + b.Property("JobXp") + .HasColumnType("integer"); + + b.Property("Level") + .HasColumnType("smallint"); + + b.Property("LightResistance") + .HasColumnType("smallint"); + + b.Property("Limiter") + .HasColumnType("smallint"); + + b.Property("MagicDefence") + .HasColumnType("smallint"); + + b.Property("MaxHp") + .HasColumnType("integer"); + + b.Property("MaxMp") + .HasColumnType("integer"); + + b.Property("Midgard") + .HasColumnType("integer"); + + b.Property("MonsterType") + .HasColumnType("smallint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("NoAggresiveIcon") + .HasColumnType("boolean"); + + b.Property("NoticeRange") + .HasColumnType("smallint"); + + b.Property("OnDefenseOnlyOnce") + .HasColumnType("boolean"); + + b.Property("PetInfoVal1") + .HasColumnType("integer"); + + b.Property("PetInfoVal2") + .HasColumnType("integer"); + + b.Property("PetInfoVal3") + .HasColumnType("integer"); + + b.Property("PetInfoVal4") + .HasColumnType("integer"); + + b.Property("Race") + .HasColumnType("smallint"); + + b.Property("RaceType") + .HasColumnType("smallint"); + + b.Property("RangeThreshold") + .HasColumnType("smallint"); + + b.Property("RegenerateHpOverTime") + .HasColumnType("boolean"); + + b.Property("RespawnTime") + .HasColumnType("integer"); + + b.Property("SpawnMobOrColor") + .HasColumnType("integer"); + + b.Property("Speed") + .HasColumnType("smallint"); + + b.Property("SpriteSize") + .HasColumnType("smallint"); + + b.Property("TakeDamages") + .HasColumnType("integer"); + + b.Property("VNumRequired") + .HasColumnType("smallint"); + + b.Property("VisibleOnMinimapAsGreenDot") + .HasColumnType("boolean"); + + b.Property("WaterResistance") + .HasColumnType("smallint"); + + b.Property("Xp") + .HasColumnType("integer"); + + b.HasKey("NpcMonsterVNum"); + + b.ToTable("NpcMonster"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.NpcMonsterSkill", b => + { + b.Property("NpcMonsterSkillId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NpcMonsterSkillId")); + + b.Property("Force") + .HasColumnType("smallint"); + + b.Property("NpcMonsterVNum") + .HasColumnType("smallint"); + + b.Property("Rate") + .HasColumnType("smallint"); + + b.Property("SkillVNum") + .HasColumnType("smallint"); + + b.HasKey("NpcMonsterSkillId"); + + b.HasIndex("NpcMonsterVNum"); + + b.HasIndex("SkillVNum"); + + b.ToTable("NpcMonsterSkill"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.NpcTalk", b => + { + b.Property("DialogId") + .ValueGeneratedOnAdd() + .HasColumnType("smallint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DialogId")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("DialogId"); + + b.ToTable("NpcTalk"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.PenaltyLog", b => + { + b.Property("PenaltyLogId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PenaltyLogId")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("AdminName") + .IsRequired() + .HasColumnType("text"); + + b.Property("DateEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("DateStart") + .HasColumnType("timestamp with time zone"); + + b.Property("Penalty") + .HasColumnType("smallint"); + + b.Property("Reason") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("PenaltyLogId"); + + b.HasIndex("AccountId"); + + b.ToTable("PenaltyLog"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Portal", b => + { + b.Property("PortalId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PortalId")); + + b.Property("DestinationMapId") + .HasColumnType("smallint"); + + b.Property("DestinationX") + .HasColumnType("smallint"); + + b.Property("DestinationY") + .HasColumnType("smallint"); + + b.Property("IsDisabled") + .HasColumnType("boolean"); + + b.Property("SourceMapId") + .HasColumnType("smallint"); + + b.Property("SourceX") + .HasColumnType("smallint"); + + b.Property("SourceY") + .HasColumnType("smallint"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.HasKey("PortalId"); + + b.HasIndex("DestinationMapId"); + + b.HasIndex("SourceMapId"); + + b.ToTable("Portal"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Quest", b => + { + b.Property("QuestId") + .HasColumnType("smallint"); + + b.Property("AutoFinish") + .HasColumnType("boolean"); + + b.Property("Desc") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("EndDialogId") + .HasColumnType("integer"); + + b.Property("IsDaily") + .HasColumnType("boolean"); + + b.Property("IsSecondary") + .HasColumnType("boolean"); + + b.Property("LevelMax") + .HasColumnType("smallint"); + + b.Property("LevelMin") + .HasColumnType("smallint"); + + b.Property("NextQuestId") + .HasColumnType("smallint"); + + b.Property("QuestType") + .HasColumnType("smallint"); + + b.Property("RequiredQuestId") + .HasColumnType("smallint"); + + b.Property("SpecialData") + .HasColumnType("integer"); + + b.Property("StartDialogId") + .HasColumnType("integer"); + + b.Property("TargetMap") + .HasColumnType("smallint"); + + b.Property("TargetX") + .HasColumnType("smallint"); + + b.Property("TargetY") + .HasColumnType("smallint"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("QuestId"); + + b.ToTable("Quest"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.QuestObjective", b => + { + b.Property("QuestObjectiveId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("FirstData") + .HasColumnType("integer"); + + b.Property("FourthData") + .HasColumnType("integer"); + + b.Property("QuestId") + .HasColumnType("smallint"); + + b.Property("SecondData") + .HasColumnType("integer"); + + b.Property("ThirdData") + .HasColumnType("integer"); + + b.HasKey("QuestObjectiveId"); + + b.HasIndex("QuestId"); + + b.ToTable("QuestObjective"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.QuestQuestReward", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("QuestId") + .HasColumnType("smallint"); + + b.Property("QuestRewardId") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("QuestId"); + + b.HasIndex("QuestRewardId"); + + b.ToTable("QuestQuestReward"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.QuestReward", b => + { + b.Property("QuestRewardId") + .ValueGeneratedOnAdd() + .HasColumnType("smallint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("QuestRewardId")); + + b.Property("Amount") + .HasColumnType("integer"); + + b.Property("Data") + .HasColumnType("integer"); + + b.Property("Design") + .HasColumnType("smallint"); + + b.Property("Rarity") + .HasColumnType("smallint"); + + b.Property("RewardType") + .HasColumnType("smallint"); + + b.Property("Upgrade") + .HasColumnType("smallint"); + + b.HasKey("QuestRewardId"); + + b.ToTable("QuestReward"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.QuicklistEntry", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CharacterId") + .HasColumnType("bigint"); + + b.Property("IconType") + .HasColumnType("smallint"); + + b.Property("IconVNum") + .HasColumnType("smallint"); + + b.Property("Morph") + .HasColumnType("smallint"); + + b.Property("QuickListIndex") + .HasColumnType("smallint"); + + b.Property("Slot") + .HasColumnType("smallint"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("CharacterId"); + + b.ToTable("QuicklistEntry"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Recipe", b => + { + b.Property("RecipeId") + .ValueGeneratedOnAdd() + .HasColumnType("smallint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RecipeId")); + + b.Property("Amount") + .HasColumnType("smallint"); + + b.Property("ItemVNum") + .HasColumnType("smallint"); + + b.Property("MapNpcId") + .HasColumnType("integer"); + + b.HasKey("RecipeId"); + + b.HasIndex("ItemVNum"); + + b.HasIndex("MapNpcId"); + + b.ToTable("Recipe"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.RecipeItem", b => + { + b.Property("RecipeItemId") + .ValueGeneratedOnAdd() + .HasColumnType("smallint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RecipeItemId")); + + b.Property("Amount") + .HasColumnType("smallint"); + + b.Property("ItemVNum") + .HasColumnType("smallint"); + + b.Property("RecipeId") + .HasColumnType("smallint"); + + b.HasKey("RecipeItemId"); + + b.HasIndex("ItemVNum"); + + b.HasIndex("RecipeId"); + + b.ToTable("RecipeItem"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Respawn", b => + { + b.Property("RespawnId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RespawnId")); + + b.Property("CharacterId") + .HasColumnType("bigint"); + + b.Property("MapId") + .HasColumnType("smallint"); + + b.Property("RespawnMapTypeId") + .HasColumnType("bigint"); + + b.Property("X") + .HasColumnType("smallint"); + + b.Property("Y") + .HasColumnType("smallint"); + + b.HasKey("RespawnId"); + + b.HasIndex("CharacterId"); + + b.HasIndex("MapId"); + + b.HasIndex("RespawnMapTypeId"); + + b.ToTable("Respawn"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.RespawnMapType", b => + { + b.Property("RespawnMapTypeId") + .HasColumnType("bigint"); + + b.Property("DefaultX") + .HasColumnType("smallint"); + + b.Property("DefaultY") + .HasColumnType("smallint"); + + b.Property("MapId") + .HasColumnType("smallint"); + + b.Property("Name") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("RespawnMapTypeId"); + + b.HasIndex("MapId"); + + b.ToTable("RespawnMapType"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.RollGeneratedItem", b => + { + b.Property("RollGeneratedItemId") + .ValueGeneratedOnAdd() + .HasColumnType("smallint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RollGeneratedItemId")); + + b.Property("IsRareRandom") + .HasColumnType("boolean"); + + b.Property("IsSuperReward") + .HasColumnType("boolean"); + + b.Property("ItemGeneratedAmount") + .HasColumnType("smallint"); + + b.Property("ItemGeneratedUpgrade") + .HasColumnType("smallint"); + + b.Property("ItemGeneratedVNum") + .HasColumnType("smallint"); + + b.Property("MaximumOriginalItemRare") + .HasColumnType("smallint"); + + b.Property("MinimumOriginalItemRare") + .HasColumnType("smallint"); + + b.Property("OriginalItemDesign") + .HasColumnType("smallint"); + + b.Property("OriginalItemVNum") + .HasColumnType("smallint"); + + b.Property("Probability") + .HasColumnType("smallint"); + + b.HasKey("RollGeneratedItemId"); + + b.HasIndex("ItemGeneratedVNum"); + + b.HasIndex("OriginalItemVNum"); + + b.ToTable("RollGeneratedItem"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Script", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Argument1") + .HasColumnType("smallint"); + + b.Property("Argument2") + .HasColumnType("smallint"); + + b.Property("Argument3") + .HasColumnType("smallint"); + + b.Property("ScriptId") + .HasColumnType("smallint"); + + b.Property("ScriptStepId") + .HasColumnType("smallint"); + + b.Property("StepType") + .IsRequired() + .HasColumnType("text"); + + b.Property("StringArgument") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ScriptId", "ScriptStepId") + .IsUnique(); + + b.ToTable("Script"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.ScriptedInstance", b => + { + b.Property("ScriptedInstanceId") + .ValueGeneratedOnAdd() + .HasColumnType("smallint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ScriptedInstanceId")); + + b.Property("IsHeroic") + .HasColumnType("boolean"); + + b.Property("Label") + .HasColumnType("text"); + + b.Property("LevelMaximum") + .HasColumnType("smallint"); + + b.Property("LevelMinimum") + .HasColumnType("smallint"); + + b.Property("MapId") + .HasColumnType("smallint"); + + b.Property("PositionX") + .HasColumnType("smallint"); + + b.Property("PositionY") + .HasColumnType("smallint"); + + b.Property("Script") + .HasMaxLength(2147483647) + .HasColumnType("text"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.HasKey("ScriptedInstanceId"); + + b.HasIndex("MapId"); + + b.ToTable("ScriptedInstance"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Shop", b => + { + b.Property("ShopId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ShopId")); + + b.Property("MapNpcId") + .HasColumnType("integer"); + + b.Property("MenuType") + .HasColumnType("smallint"); + + b.Property("ShopType") + .HasColumnType("smallint"); + + b.HasKey("ShopId"); + + b.HasIndex("MapNpcId"); + + b.ToTable("Shop"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.ShopItem", b => + { + b.Property("ShopItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ShopItemId")); + + b.Property("Color") + .HasColumnType("smallint"); + + b.Property("ItemVNum") + .HasColumnType("smallint"); + + b.Property("Rare") + .HasColumnType("smallint"); + + b.Property("ShopId") + .HasColumnType("integer"); + + b.Property("Slot") + .HasColumnType("smallint"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.Property("Upgrade") + .HasColumnType("smallint"); + + b.HasKey("ShopItemId"); + + b.HasIndex("ItemVNum"); + + b.HasIndex("ShopId"); + + b.ToTable("ShopItem"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.ShopSkill", b => + { + b.Property("ShopSkillId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ShopSkillId")); + + b.Property("ShopId") + .HasColumnType("integer"); + + b.Property("SkillVNum") + .HasColumnType("smallint"); + + b.Property("Slot") + .HasColumnType("smallint"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.HasKey("ShopSkillId"); + + b.HasIndex("ShopId"); + + b.HasIndex("SkillVNum"); + + b.ToTable("ShopSkill"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Skill", b => + { + b.Property("SkillVNum") + .HasColumnType("smallint"); + + b.Property("AttackAnimation") + .HasColumnType("smallint"); + + b.Property("CastAnimation") + .HasColumnType("smallint"); + + b.Property("CastEffect") + .HasColumnType("smallint"); + + b.Property("CastId") + .HasColumnType("smallint"); + + b.Property("CastTime") + .HasColumnType("smallint"); + + b.Property("Class") + .HasColumnType("smallint"); + + b.Property("Cooldown") + .HasColumnType("smallint"); + + b.Property("CpCost") + .HasColumnType("smallint"); + + b.Property("Duration") + .HasColumnType("smallint"); + + b.Property("Effect") + .HasColumnType("smallint"); + + b.Property("Element") + .HasColumnType("smallint"); + + b.Property("HitType") + .HasColumnType("smallint"); + + b.Property("ItemVNum") + .HasColumnType("smallint"); + + b.Property("Level") + .HasColumnType("smallint"); + + b.Property("LevelMinimum") + .HasColumnType("smallint"); + + b.Property("MinimumAdventurerLevel") + .HasColumnType("smallint"); + + b.Property("MinimumArcherLevel") + .HasColumnType("smallint"); + + b.Property("MinimumMagicianLevel") + .HasColumnType("smallint"); + + b.Property("MinimumSwordmanLevel") + .HasColumnType("smallint"); + + b.Property("MpCost") + .HasColumnType("smallint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("Price") + .HasColumnType("integer"); + + b.Property("Range") + .HasColumnType("smallint"); + + b.Property("SkillType") + .HasColumnType("smallint"); + + b.Property("TargetRange") + .HasColumnType("smallint"); + + b.Property("TargetType") + .HasColumnType("smallint"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.Property("UpgradeSkill") + .HasColumnType("smallint"); + + b.Property("UpgradeType") + .HasColumnType("smallint"); + + b.HasKey("SkillVNum"); + + b.ToTable("Skill"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.StaticBonus", b => + { + b.Property("StaticBonusId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("StaticBonusId")); + + b.Property("CharacterId") + .HasColumnType("bigint"); + + b.Property("DateEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("StaticBonusType") + .HasColumnType("smallint"); + + b.HasKey("StaticBonusId"); + + b.HasIndex("CharacterId"); + + b.ToTable("StaticBonus"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.StaticBuff", b => + { + b.Property("StaticBuffId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("StaticBuffId")); + + b.Property("CardId") + .HasColumnType("smallint"); + + b.Property("CharacterId") + .HasColumnType("bigint"); + + b.Property("RemainingTime") + .HasColumnType("integer"); + + b.HasKey("StaticBuffId"); + + b.HasIndex("CardId"); + + b.HasIndex("CharacterId"); + + b.ToTable("StaticBuff"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Teleporter", b => + { + b.Property("TeleporterId") + .ValueGeneratedOnAdd() + .HasColumnType("smallint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TeleporterId")); + + b.Property("Index") + .HasColumnType("smallint"); + + b.Property("MapId") + .HasColumnType("smallint"); + + b.Property("MapNpcId") + .HasColumnType("integer"); + + b.Property("MapX") + .HasColumnType("smallint"); + + b.Property("MapY") + .HasColumnType("smallint"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.HasKey("TeleporterId"); + + b.HasIndex("MapId"); + + b.HasIndex("MapNpcId"); + + b.ToTable("Teleporter"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Title", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("CharacterId") + .HasColumnType("bigint"); + + b.Property("TitleType") + .HasColumnType("smallint"); + + b.Property("Visible") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("CharacterId", "TitleType") + .IsUnique(); + + b.ToTable("Title"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Warehouse", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CharacterId") + .HasColumnType("bigint"); + + b.Property("FamilyId") + .HasColumnType("bigint"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("CharacterId"); + + b.HasIndex("FamilyId"); + + b.ToTable("Warehouse"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.WarehouseItem", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ItemInstanceId") + .HasColumnType("uuid"); + + b.Property("Slot") + .HasColumnType("smallint"); + + b.Property("WarehouseId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ItemInstanceId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("WarehouseItem"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.UsableInstance", b => + { + b.HasBaseType("NosCore.Database.Entities.ItemInstance"); + + b.Property("Hp") + .HasColumnType("smallint"); + + b.Property("Mp") + .HasColumnType("smallint"); + + b.ToTable("ItemInstance", t => + { + t.Property("Hp") + .HasColumnName("UsableInstance_Hp"); + + t.Property("Mp") + .HasColumnName("UsableInstance_Mp"); + }); + + b.HasDiscriminator().HasValue("UsableInstance"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.WearableInstance", b => + { + b.HasBaseType("NosCore.Database.Entities.ItemInstance"); + + b.Property("Ammo") + .HasColumnType("smallint"); + + b.Property("Cellon") + .HasColumnType("smallint"); + + b.Property("CloseDefence") + .HasColumnType("smallint"); + + b.Property("Concentrate") + .HasColumnType("smallint"); + + b.Property("CriticalDodge") + .HasColumnType("smallint"); + + b.Property("CriticalLuckRate") + .HasColumnType("smallint"); + + b.Property("CriticalRate") + .HasColumnType("smallint"); + + b.Property("DamageMaximum") + .HasColumnType("smallint"); + + b.Property("DamageMinimum") + .HasColumnType("smallint"); + + b.Property("DarkElement") + .HasColumnType("smallint"); + + b.Property("DarkResistance") + .HasColumnType("smallint"); + + b.Property("DefenceDodge") + .HasColumnType("smallint"); + + b.Property("DistanceDefence") + .HasColumnType("smallint"); + + b.Property("DistanceDefenceDodge") + .HasColumnType("smallint"); + + b.Property("ElementRate") + .HasColumnType("smallint"); + + b.Property("FireElement") + .HasColumnType("smallint"); + + b.Property("FireResistance") + .HasColumnType("smallint"); + + b.Property("HitRate") + .HasColumnType("smallint"); + + b.Property("Hp") + .HasColumnType("smallint"); + + b.Property("IsEmpty") + .HasColumnType("boolean"); + + b.Property("IsFixed") + .HasColumnType("boolean"); + + b.Property("LightElement") + .HasColumnType("smallint"); + + b.Property("LightResistance") + .HasColumnType("smallint"); + + b.Property("MagicDefence") + .HasColumnType("smallint"); + + b.Property("MaxElementRate") + .HasColumnType("smallint"); + + b.Property("Mp") + .HasColumnType("smallint"); + + b.Property("ShellRarity") + .HasColumnType("smallint"); + + b.Property("WaterElement") + .HasColumnType("smallint"); + + b.Property("WaterResistance") + .HasColumnType("smallint"); + + b.Property("Xp") + .HasColumnType("bigint"); + + b.HasDiscriminator().HasValue("WearableInstance"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.SpecialistInstance", b => + { + b.HasBaseType("NosCore.Database.Entities.WearableInstance"); + + b.Property("SlDamage") + .HasColumnType("smallint"); + + b.Property("SlDefence") + .HasColumnType("smallint"); + + b.Property("SlElement") + .HasColumnType("smallint"); + + b.Property("SlHp") + .HasColumnType("smallint"); + + b.Property("SpDamage") + .HasColumnType("smallint"); + + b.Property("SpDark") + .HasColumnType("smallint"); + + b.Property("SpDefence") + .HasColumnType("smallint"); + + b.Property("SpElement") + .HasColumnType("smallint"); + + b.Property("SpFire") + .HasColumnType("smallint"); + + b.Property("SpHp") + .HasColumnType("smallint"); + + b.Property("SpLevel") + .HasColumnType("smallint"); + + b.Property("SpLight") + .HasColumnType("smallint"); + + b.Property("SpStoneUpgrade") + .HasColumnType("smallint"); + + b.Property("SpWater") + .HasColumnType("smallint"); + + b.HasDiscriminator().HasValue("SpecialistInstance"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.BoxInstance", b => + { + b.HasBaseType("NosCore.Database.Entities.SpecialistInstance"); + + b.Property("HoldingVNum") + .HasColumnType("smallint"); + + b.HasDiscriminator().HasValue("BoxInstance"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.ActPart", b => + { + b.HasOne("NosCore.Database.Entities.Act", "Act") + .WithMany("ActParts") + .HasForeignKey("ActId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Act"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.BCard", b => + { + b.HasOne("NosCore.Database.Entities.Card", "Card") + .WithMany("BCards") + .HasForeignKey("CardId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("NosCore.Database.Entities.Item", "Item") + .WithMany("BCards") + .HasForeignKey("ItemVNum") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("NosCore.Database.Entities.NpcMonster", "NpcMonster") + .WithMany("BCards") + .HasForeignKey("NpcMonsterVNum") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("NosCore.Database.Entities.Skill", "Skill") + .WithMany("BCards") + .HasForeignKey("SkillVNum") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Card"); + + b.Navigation("Item"); + + b.Navigation("NpcMonster"); + + b.Navigation("Skill"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.BazaarItem", b => + { + b.HasOne("NosCore.Database.Entities.ItemInstance", "ItemInstance") + .WithMany("BazaarItem") + .HasForeignKey("ItemInstanceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.Character", "Seller") + .WithMany("BazaarItem") + .HasForeignKey("SellerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("ItemInstance"); + + b.Navigation("Seller"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Character", b => + { + b.HasOne("NosCore.Database.Entities.Account", "Account") + .WithMany("Character") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.Script", "Script") + .WithMany("Characters") + .HasForeignKey("CurrentScriptId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("NosCore.Database.Entities.Map", "Map") + .WithMany("Character") + .HasForeignKey("MapId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Account"); + + b.Navigation("Map"); + + b.Navigation("Script"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.CharacterActPart", b => + { + b.HasOne("NosCore.Database.Entities.ActPart", "ActPart") + .WithMany("CharacterActParts") + .HasForeignKey("ActPartId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.Character", "Character") + .WithMany("CharacterActParts") + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("ActPart"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.CharacterQuest", b => + { + b.HasOne("NosCore.Database.Entities.Character", "Character") + .WithMany("CharacterQuest") + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.Quest", "Quest") + .WithMany("CharacterQuest") + .HasForeignKey("QuestId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Character"); + + b.Navigation("Quest"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.CharacterQuestObjective", b => + { + b.HasOne("NosCore.Database.Entities.CharacterQuest", "CharacterQuest") + .WithMany("CharacterQuestObjective") + .HasForeignKey("CharacterQuestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.QuestObjective", "QuestObjective") + .WithMany("CharacterQuestObjective") + .HasForeignKey("QuestObjectiveId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CharacterQuest"); + + b.Navigation("QuestObjective"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.CharacterRelation", b => + { + b.HasOne("NosCore.Database.Entities.Character", "Character1") + .WithMany("CharacterRelation1") + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.Character", "Character2") + .WithMany("CharacterRelation2") + .HasForeignKey("RelatedCharacterId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Character1"); + + b.Navigation("Character2"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.CharacterSkill", b => + { + b.HasOne("NosCore.Database.Entities.Character", "Character") + .WithMany("CharacterSkill") + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.Skill", "Skill") + .WithMany("CharacterSkill") + .HasForeignKey("SkillVNum") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Character"); + + b.Navigation("Skill"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Combo", b => + { + b.HasOne("NosCore.Database.Entities.Skill", "Skill") + .WithMany("Combo") + .HasForeignKey("SkillVNum") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Skill"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Drop", b => + { + b.HasOne("NosCore.Database.Entities.MapType", "MapType") + .WithMany("Drops") + .HasForeignKey("MapTypeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("NosCore.Database.Entities.NpcMonster", "NpcMonster") + .WithMany("Drop") + .HasForeignKey("MonsterVNum") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("NosCore.Database.Entities.Item", "Item") + .WithMany("Drop") + .HasForeignKey("VNum") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("MapType"); + + b.Navigation("NpcMonster"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.EquipmentOption", b => + { + b.HasOne("NosCore.Database.Entities.WearableInstance", "WearableInstance") + .WithMany() + .HasForeignKey("WearableInstanceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("WearableInstance"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.FamilyCharacter", b => + { + b.HasOne("NosCore.Database.Entities.Character", "Character") + .WithMany("FamilyCharacter") + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.Family", "Family") + .WithMany("FamilyCharacters") + .HasForeignKey("FamilyId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Character"); + + b.Navigation("Family"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.FamilyLog", b => + { + b.HasOne("NosCore.Database.Entities.Family", "Family") + .WithMany("FamilyLogs") + .HasForeignKey("FamilyId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Family"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.InventoryItemInstance", b => + { + b.HasOne("NosCore.Database.Entities.Character", "Character") + .WithMany("Inventory") + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.ItemInstance", "ItemInstance") + .WithMany("InventoryItemInstance") + .HasForeignKey("ItemInstanceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Character"); + + b.Navigation("ItemInstance"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.ItemInstance", b => + { + b.HasOne("NosCore.Database.Entities.Character", "BoundCharacter") + .WithMany() + .HasForeignKey("BoundCharacterId"); + + b.HasOne("NosCore.Database.Entities.Item", "Item") + .WithMany("ItemInstances") + .HasForeignKey("ItemVNum") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BoundCharacter"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Mail", b => + { + b.HasOne("NosCore.Database.Entities.ItemInstance", "ItemInstance") + .WithMany("Mail") + .HasForeignKey("ItemInstanceId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("NosCore.Database.Entities.Character", "Receiver") + .WithMany("Mail1") + .HasForeignKey("ReceiverId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.Character", "Sender") + .WithMany("Mail") + .HasForeignKey("SenderId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("ItemInstance"); + + b.Navigation("Receiver"); + + b.Navigation("Sender"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.MapMonster", b => + { + b.HasOne("NosCore.Database.Entities.Map", "Map") + .WithMany("MapMonster") + .HasForeignKey("MapId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.NpcMonster", "NpcMonster") + .WithMany("MapMonster") + .HasForeignKey("VNum") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Map"); + + b.Navigation("NpcMonster"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.MapNpc", b => + { + b.HasOne("NosCore.Database.Entities.NpcTalk", "NpcTalk") + .WithMany("MapNpc") + .HasForeignKey("Dialog") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("NosCore.Database.Entities.Map", "Map") + .WithMany("MapNpc") + .HasForeignKey("MapId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.NpcMonster", "NpcMonster") + .WithMany("MapNpc") + .HasForeignKey("VNum") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Map"); + + b.Navigation("NpcMonster"); + + b.Navigation("NpcTalk"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.MapType", b => + { + b.HasOne("NosCore.Database.Entities.RespawnMapType", "RespawnMapType") + .WithMany("MapTypes") + .HasForeignKey("RespawnMapTypeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("NosCore.Database.Entities.RespawnMapType", "ReturnMapType") + .WithMany("MapTypes1") + .HasForeignKey("ReturnMapTypeId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("RespawnMapType"); + + b.Navigation("ReturnMapType"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.MapTypeMap", b => + { + b.HasOne("NosCore.Database.Entities.Map", "Map") + .WithMany("MapTypeMap") + .HasForeignKey("MapId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.MapType", "MapType") + .WithMany("MapTypeMap") + .HasForeignKey("MapTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Map"); + + b.Navigation("MapType"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Mate", b => + { + b.HasOne("NosCore.Database.Entities.Character", "Character") + .WithMany("Mate") + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.NpcMonster", "NpcMonster") + .WithMany("Mate") + .HasForeignKey("VNum") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Character"); + + b.Navigation("NpcMonster"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Miniland", b => + { + b.HasOne("NosCore.Database.Entities.Character", "Owner") + .WithMany("Miniland") + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.MinilandObject", b => + { + b.HasOne("NosCore.Database.Entities.InventoryItemInstance", "InventoryItemInstance") + .WithMany("MinilandObject") + .HasForeignKey("InventoryItemInstanceId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("InventoryItemInstance"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.NpcMonsterSkill", b => + { + b.HasOne("NosCore.Database.Entities.NpcMonster", "NpcMonster") + .WithMany("NpcMonsterSkill") + .HasForeignKey("NpcMonsterVNum") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.Skill", "Skill") + .WithMany("NpcMonsterSkill") + .HasForeignKey("SkillVNum") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("NpcMonster"); + + b.Navigation("Skill"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.PenaltyLog", b => + { + b.HasOne("NosCore.Database.Entities.Account", "Account") + .WithMany("PenaltyLog") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Portal", b => + { + b.HasOne("NosCore.Database.Entities.Map", "Map") + .WithMany("Portal") + .HasForeignKey("DestinationMapId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.Map", "Map1") + .WithMany("Portal1") + .HasForeignKey("SourceMapId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Map"); + + b.Navigation("Map1"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.QuestObjective", b => + { + b.HasOne("NosCore.Database.Entities.Quest", "Quest") + .WithMany("QuestObjective") + .HasForeignKey("QuestId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Quest"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.QuestQuestReward", b => + { + b.HasOne("NosCore.Database.Entities.Quest", "Quest") + .WithMany("QuestQuestReward") + .HasForeignKey("QuestId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.QuestReward", "QuestReward") + .WithMany("QuestQuestReward") + .HasForeignKey("QuestRewardId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Quest"); + + b.Navigation("QuestReward"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.QuicklistEntry", b => + { + b.HasOne("NosCore.Database.Entities.Character", "Character") + .WithMany("QuicklistEntry") + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Recipe", b => + { + b.HasOne("NosCore.Database.Entities.Item", "Item") + .WithMany("Recipe") + .HasForeignKey("ItemVNum") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.MapNpc", "MapNpc") + .WithMany("Recipe") + .HasForeignKey("MapNpcId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("MapNpc"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.RecipeItem", b => + { + b.HasOne("NosCore.Database.Entities.Item", "Item") + .WithMany("RecipeItem") + .HasForeignKey("ItemVNum") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.Recipe", "Recipe") + .WithMany("RecipeItem") + .HasForeignKey("RecipeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Recipe"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Respawn", b => + { + b.HasOne("NosCore.Database.Entities.Character", "Character") + .WithMany("Respawn") + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.Map", "Map") + .WithMany("Respawn") + .HasForeignKey("MapId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.RespawnMapType", "RespawnMapType") + .WithMany("Respawn") + .HasForeignKey("RespawnMapTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Character"); + + b.Navigation("Map"); + + b.Navigation("RespawnMapType"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.RespawnMapType", b => + { + b.HasOne("NosCore.Database.Entities.Map", "Map") + .WithMany("RespawnMapType") + .HasForeignKey("MapId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Map"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.RollGeneratedItem", b => + { + b.HasOne("NosCore.Database.Entities.Item", "ItemGenerated") + .WithMany("RollGeneratedItem2") + .HasForeignKey("ItemGeneratedVNum") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.Item", "OriginalItem") + .WithMany("RollGeneratedItem") + .HasForeignKey("OriginalItemVNum") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("ItemGenerated"); + + b.Navigation("OriginalItem"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.ScriptedInstance", b => + { + b.HasOne("NosCore.Database.Entities.Map", "Map") + .WithMany("ScriptedInstance") + .HasForeignKey("MapId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Map"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Shop", b => + { + b.HasOne("NosCore.Database.Entities.MapNpc", "MapNpc") + .WithMany("Shop") + .HasForeignKey("MapNpcId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("MapNpc"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.ShopItem", b => + { + b.HasOne("NosCore.Database.Entities.Item", "Item") + .WithMany("ShopItem") + .HasForeignKey("ItemVNum") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.Shop", "Shop") + .WithMany("ShopItem") + .HasForeignKey("ShopId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Shop"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.ShopSkill", b => + { + b.HasOne("NosCore.Database.Entities.Shop", "Shop") + .WithMany("ShopSkill") + .HasForeignKey("ShopId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.Skill", "Skill") + .WithMany("ShopSkill") + .HasForeignKey("SkillVNum") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Shop"); + + b.Navigation("Skill"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.StaticBonus", b => + { + b.HasOne("NosCore.Database.Entities.Character", "Character") + .WithMany("StaticBonus") + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.StaticBuff", b => + { + b.HasOne("NosCore.Database.Entities.Card", "Card") + .WithMany("StaticBuff") + .HasForeignKey("CardId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.Character", "Character") + .WithMany("StaticBuff") + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Card"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Teleporter", b => + { + b.HasOne("NosCore.Database.Entities.Map", "Map") + .WithMany("Teleporter") + .HasForeignKey("MapId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.MapNpc", "MapNpc") + .WithMany("Teleporter") + .HasForeignKey("MapNpcId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Map"); + + b.Navigation("MapNpc"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Title", b => + { + b.HasOne("NosCore.Database.Entities.Character", "Character") + .WithMany("Title") + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Warehouse", b => + { + b.HasOne("NosCore.Database.Entities.Character", "Character") + .WithMany("Warehouses") + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("NosCore.Database.Entities.Family", "Family") + .WithMany("Warehouses") + .HasForeignKey("FamilyId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Character"); + + b.Navigation("Family"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.WarehouseItem", b => + { + b.HasOne("NosCore.Database.Entities.ItemInstance", "ItemInstance") + .WithMany("WarehouseItems") + .HasForeignKey("ItemInstanceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("NosCore.Database.Entities.Warehouse", "Warehouse") + .WithMany("WarehouseItems") + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("ItemInstance"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Account", b => + { + b.Navigation("Character"); + + b.Navigation("PenaltyLog"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Act", b => + { + b.Navigation("ActParts"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.ActPart", b => + { + b.Navigation("CharacterActParts"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Card", b => + { + b.Navigation("BCards"); + + b.Navigation("StaticBuff"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Character", b => + { + b.Navigation("BazaarItem"); + + b.Navigation("CharacterActParts"); + + b.Navigation("CharacterQuest"); + + b.Navigation("CharacterRelation1"); + + b.Navigation("CharacterRelation2"); + + b.Navigation("CharacterSkill"); + + b.Navigation("FamilyCharacter"); + + b.Navigation("Inventory"); + + b.Navigation("Mail"); + + b.Navigation("Mail1"); + + b.Navigation("Mate"); + + b.Navigation("Miniland"); + + b.Navigation("QuicklistEntry"); + + b.Navigation("Respawn"); + + b.Navigation("StaticBonus"); + + b.Navigation("StaticBuff"); + + b.Navigation("Title"); + + b.Navigation("Warehouses"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.CharacterQuest", b => + { + b.Navigation("CharacterQuestObjective"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Family", b => + { + b.Navigation("FamilyCharacters"); + + b.Navigation("FamilyLogs"); + + b.Navigation("Warehouses"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.InventoryItemInstance", b => + { + b.Navigation("MinilandObject"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Item", b => + { + b.Navigation("BCards"); + + b.Navigation("Drop"); + + b.Navigation("ItemInstances"); + + b.Navigation("Recipe"); + + b.Navigation("RecipeItem"); + + b.Navigation("RollGeneratedItem"); + + b.Navigation("RollGeneratedItem2"); + + b.Navigation("ShopItem"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.ItemInstance", b => + { + b.Navigation("BazaarItem"); + + b.Navigation("InventoryItemInstance"); + + b.Navigation("Mail"); + + b.Navigation("WarehouseItems"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Map", b => + { + b.Navigation("Character"); + + b.Navigation("MapMonster"); + + b.Navigation("MapNpc"); + + b.Navigation("MapTypeMap"); + + b.Navigation("Portal"); + + b.Navigation("Portal1"); + + b.Navigation("Respawn"); + + b.Navigation("RespawnMapType"); + + b.Navigation("ScriptedInstance"); + + b.Navigation("Teleporter"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.MapNpc", b => + { + b.Navigation("Recipe"); + + b.Navigation("Shop"); + + b.Navigation("Teleporter"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.MapType", b => + { + b.Navigation("Drops"); + + b.Navigation("MapTypeMap"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.NpcMonster", b => + { + b.Navigation("BCards"); + + b.Navigation("Drop"); + + b.Navigation("MapMonster"); + + b.Navigation("MapNpc"); + + b.Navigation("Mate"); + + b.Navigation("NpcMonsterSkill"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.NpcTalk", b => + { + b.Navigation("MapNpc"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Quest", b => + { + b.Navigation("CharacterQuest"); + + b.Navigation("QuestObjective"); + + b.Navigation("QuestQuestReward"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.QuestObjective", b => + { + b.Navigation("CharacterQuestObjective"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.QuestReward", b => + { + b.Navigation("QuestQuestReward"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Recipe", b => + { + b.Navigation("RecipeItem"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.RespawnMapType", b => + { + b.Navigation("MapTypes"); + + b.Navigation("MapTypes1"); + + b.Navigation("Respawn"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Script", b => + { + b.Navigation("Characters"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Shop", b => + { + b.Navigation("ShopItem"); + + b.Navigation("ShopSkill"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Skill", b => + { + b.Navigation("BCards"); + + b.Navigation("CharacterSkill"); + + b.Navigation("Combo"); + + b.Navigation("NpcMonsterSkill"); + + b.Navigation("ShopSkill"); + }); + + modelBuilder.Entity("NosCore.Database.Entities.Warehouse", b => + { + b.Navigation("WarehouseItems"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/NosCore.Database/Migrations/20260822232419_AddScriptedInstanceEntryDetails.cs b/src/NosCore.Database/Migrations/20260822232419_AddScriptedInstanceEntryDetails.cs new file mode 100644 index 000000000..e8f1ec2d0 --- /dev/null +++ b/src/NosCore.Database/Migrations/20260822232419_AddScriptedInstanceEntryDetails.cs @@ -0,0 +1,51 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace NosCore.Database.Migrations +{ + /// + public partial class AddScriptedInstanceEntryDetails : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "IsHeroic", + table: "ScriptedInstance", + type: "boolean", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "LevelMaximum", + table: "ScriptedInstance", + type: "smallint", + nullable: false, + defaultValue: (byte)0); + + migrationBuilder.AddColumn( + name: "LevelMinimum", + table: "ScriptedInstance", + type: "smallint", + nullable: false, + defaultValue: (byte)0); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "IsHeroic", + table: "ScriptedInstance"); + + migrationBuilder.DropColumn( + name: "LevelMaximum", + table: "ScriptedInstance"); + + migrationBuilder.DropColumn( + name: "LevelMinimum", + table: "ScriptedInstance"); + } + } +} diff --git a/src/NosCore.Database/Migrations/NosCoreContextModelSnapshot.cs b/src/NosCore.Database/Migrations/NosCoreContextModelSnapshot.cs index a7cbadf15..eff3c4b1f 100644 --- a/src/NosCore.Database/Migrations/NosCoreContextModelSnapshot.cs +++ b/src/NosCore.Database/Migrations/NosCoreContextModelSnapshot.cs @@ -18,7 +18,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "10.0.6") + .HasAnnotation("ProductVersion", "10.0.11") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "audit_log_type", new[] { "account_creation", "character_creation", "email_update" }); @@ -2577,9 +2577,18 @@ protected override void BuildModel(ModelBuilder modelBuilder) NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ScriptedInstanceId")); + b.Property("IsHeroic") + .HasColumnType("boolean"); + b.Property("Label") .HasColumnType("text"); + b.Property("LevelMaximum") + .HasColumnType("smallint"); + + b.Property("LevelMinimum") + .HasColumnType("smallint"); + b.Property("MapId") .HasColumnType("smallint"); diff --git a/src/NosCore.Parser/ImportFactory.cs b/src/NosCore.Parser/ImportFactory.cs index 3dcaf50f1..125834743 100644 --- a/src/NosCore.Parser/ImportFactory.cs +++ b/src/NosCore.Parser/ImportFactory.cs @@ -28,6 +28,7 @@ public class ImportFactory(CardParser cardParser, DropParser dropParser, ItemPar PortalParser portalParser, RespawnMapTypeParser respawnMapTypeParser, ShopItemParser shopItemParser, ShopParser shopParser, SkillParser skillParser, NpcTalkParser npcTalkParser, QuestPrizeParser questPrizeParser, QuestParser questParser, ActParser actParser, ScriptParser scriptParser, + ScriptedInstanceParser scriptedInstanceParser, IDao accountDao, IDao i18NQuestDao, IDao i18NSkillDao, IDao i18NNpcMonsterTalkDao, IDao i18NNpcMonsterDao, IDao i18NMapPointDataDao, @@ -160,6 +161,11 @@ public Task ImportPortalsAsync() return portalParser.InsertPortalsAsync(_packetList); } + public Task ImportScriptedInstancesAsync() + { + return scriptedInstanceParser.InsertScriptedInstancesAsync(_packetList); + } + public async Task ImportI18NAsync() { await new I18NParser(i18NActDescDao, loggerFactory.CreateLogger>(), logLanguage).InsertI18NAsync(_folder + Path.DirectorySeparatorChar + "_code_{0}_act_desc.txt", LogLanguageKey.I18N_ACTDESC_PARSED); diff --git a/src/NosCore.Parser/Parser.cs b/src/NosCore.Parser/Parser.cs index de3f1ba6e..8325f3225 100644 --- a/src/NosCore.Parser/Parser.cs +++ b/src/NosCore.Parser/Parser.cs @@ -99,6 +99,7 @@ private async Task RunFullImportAsync() await factory.ImportMapTypeAsync().ConfigureAwait(false); await factory.ImportMapTypeMapAsync().ConfigureAwait(false); await factory.ImportPortalsAsync().ConfigureAwait(false); + await factory.ImportScriptedInstancesAsync().ConfigureAwait(false); await factory.ImportI18NAsync().ConfigureAwait(false); await factory.ImportItemsAsync().ConfigureAwait(false); await factory.ImportSkillsAsync().ConfigureAwait(false); @@ -143,7 +144,8 @@ private async Task RunPromptedImportsAsync() if (key.KeyChar != 'n') await factory.ImportI18NAsync().ConfigureAwait(false); logger.LogInformation($"{logLanguage[LogLanguageKey.PARSE_TIMESPACES]} [Y/n]"); - Console.ReadKey(true); + key = Console.ReadKey(true); + if (key.KeyChar != 'n') await factory.ImportScriptedInstancesAsync().ConfigureAwait(false); logger.LogInformation($"{logLanguage[LogLanguageKey.PARSE_ITEMS]} [Y/n]"); key = Console.ReadKey(true); diff --git a/src/NosCore.Parser/Parsers/ScriptedInstanceParser.cs b/src/NosCore.Parser/Parsers/ScriptedInstanceParser.cs new file mode 100644 index 000000000..6000dcb17 --- /dev/null +++ b/src/NosCore.Parser/Parsers/ScriptedInstanceParser.cs @@ -0,0 +1,114 @@ +// __ _ __ __ ___ __ ___ ___ +// | \| |/__\ /' _/ / _//__\| _ \ __| +// | | ' | \/ |`._`.| \_| \/ | v / _| +// |_|\__|\__/ |___/ \__/\__/|_|_\___| +// + +using Microsoft.Extensions.Logging; +using NosCore.Dao.Interfaces; +using NosCore.Data.Enumerations.I18N; +using NosCore.Data.Enumerations.Interaction; +using NosCore.Data.StaticEntities; +using NosCore.Packets.Enumerations; +using NosCore.Shared.I18N; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Threading.Tasks; + +namespace NosCore.Parser.Parsers +{ + public class ScriptedInstanceParser(ILogger logger, + IDao mapDao, IDao scriptedInstanceDao, + ILogLanguageLocalizer logLanguage) + { + private static readonly PortalType[] RaidPortals = + [PortalType.Raid, PortalType.BlueRaid, PortalType.DarkRaid]; + + public async Task InsertScriptedInstancesAsync(List packetList) + { + var maps = mapDao.LoadAll().Select(s => s.MapId).ToHashSet(); + var stored = scriptedInstanceDao.LoadAll() + .ToDictionary(s => (s.MapId, s.PositionX, s.PositionY), s => s); + var seen = new HashSet<(short, short, short)>(); + var found = new List(); + short currentMap = 0; + + foreach (var line in packetList) + { + switch (line[0]) + { + case "at" when line.Length > 5: + currentMap = short.Parse(line[2], CultureInfo.InvariantCulture); + continue; + + case "wp" when line.Length > 6: + Collect(new ScriptedInstanceDto + { + MapId = currentMap, + PositionX = short.Parse(line[1], CultureInfo.InvariantCulture), + PositionY = short.Parse(line[2], CultureInfo.InvariantCulture), + Type = ScriptedInstanceType.TimeSpace, + IsHeroic = (byte.Parse(line[4], CultureInfo.InvariantCulture) & 8) != 0, + LevelMinimum = byte.Parse(line[5], CultureInfo.InvariantCulture), + LevelMaximum = byte.Parse(line[6], CultureInfo.InvariantCulture) + }); + continue; + + case "gp" when line.Length > 4: + if (!System.Enum.TryParse(line[4], out var portalType) + || !RaidPortals.Contains(portalType)) + { + continue; + } + + Collect(new ScriptedInstanceDto + { + MapId = currentMap, + PositionX = short.Parse(line[1], CultureInfo.InvariantCulture), + PositionY = short.Parse(line[2], CultureInfo.InvariantCulture), + Type = ScriptedInstanceType.Raid + }); + continue; + } + } + + await scriptedInstanceDao.TryInsertOrUpdateAsync(found).ConfigureAwait(false); + logger.LogInformation(logLanguage[LogLanguageKey.TIMESPACES_PARSED], found.Count); + return; + + void Collect(ScriptedInstanceDto entrance) + { + if (!maps.Contains(entrance.MapId)) + { + return; + } + + var key = (entrance.MapId, entrance.PositionX, entrance.PositionY); + + // Within one run the same entrance can turn up more than once - the capture walks + // a map twice and the wp comes round again. First reading wins. + if (!seen.Add(key)) + { + return; + } + + // An entrance already in the table gets its metadata refreshed rather than + // skipped. Skipping it looked safe and was not: the columns this parser exists to + // fill arrive from the migration as 0, 0 and false, so on any database that + // already holds entrances the import would leave every level range at zero and + // every raid non-heroic - and say nothing. + // + // The id and the script come from the stored row: the id so the upsert updates + // instead of inserting a duplicate, the script because it is not ours to write. + if (stored.TryGetValue(key, out var existing)) + { + entrance.ScriptedInstanceId = existing.ScriptedInstanceId; + entrance.Script = existing.Script; + } + + found.Add(entrance); + } + } + } +} diff --git a/test/NosCore.Parser.Tests/ScriptedInstanceParserTests.cs b/test/NosCore.Parser.Tests/ScriptedInstanceParserTests.cs new file mode 100644 index 000000000..44f8e13f6 --- /dev/null +++ b/test/NosCore.Parser.Tests/ScriptedInstanceParserTests.cs @@ -0,0 +1,200 @@ +// __ _ __ __ ___ __ ___ ___ +// | \| |/__\ /' _/ / _//__\| _ \ __| +// | | ' | \/ |`._`.| \_| \/ | v / _| +// |_|\__|\__/ |___/ \__/\__/|_|_\___| +// + +using Microsoft.Extensions.Logging; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using NosCore.Dao.Interfaces; +using NosCore.Data.Enumerations.I18N; +using NosCore.Data.Enumerations.Interaction; +using NosCore.Data.StaticEntities; +using NosCore.Parser.Parsers; +using NosCore.Shared.I18N; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace NosCore.Parser.Tests +{ + [TestClass] + public class ScriptedInstanceParserTests + { + private Mock> _mapDao = null!; + private Mock> _instanceDao = null!; + private List _saved = null!; + private List _existing = null!; + private ScriptedInstanceParser _parser = null!; + + [TestInitialize] + public void Setup() + { + _saved = []; + _existing = []; + + _mapDao = new Mock>(); + _mapDao.Setup(s => s.LoadAll()).Returns(new List + { + new() { MapId = 1 }, new() { MapId = 2 }, new() { MapId = 132 }, + new() { MapId = 133 }, new() { MapId = 2500 } + }); + + _instanceDao = new Mock>(); + _instanceDao.Setup(s => s.LoadAll()).Returns(() => _existing); + _instanceDao.Setup(s => s.TryInsertOrUpdateAsync(It.IsAny>())) + .Callback>(rows => _saved.AddRange(rows)) + .ReturnsAsync(true); + + _parser = new ScriptedInstanceParser(new Mock>().Object, + _mapDao.Object, _instanceDao.Object, + new Mock>().Object); + } + + private static string[] Line(string packet) => packet.Split(' '); + + private static List Capture(params string[] packets) => packets.Select(Line).ToList(); + + [TestMethod] + public async Task AWaypointBecomesATimeSpaceEntranceOnTheMapItFollowsAsync() + { + await _parser.InsertScriptedInstancesAsync(Capture( + "at 1234 1 79 108 2 0 0 0", + "wp 134 36 0 4 1 99")); + + Assert.AreEqual(1, _saved.Count); + var entrance = _saved[0]; + Assert.AreEqual(1, entrance.MapId); + Assert.AreEqual(134, entrance.PositionX); + Assert.AreEqual(36, entrance.PositionY); + Assert.AreEqual(ScriptedInstanceType.TimeSpace, entrance.Type); + Assert.AreEqual(1, entrance.LevelMinimum); + Assert.AreEqual(99, entrance.LevelMaximum); + } + + [TestMethod] + public async Task ThePortalTypeSaysHeroOrNormalAndNothingAboutTheCaptureSPlayerAsync() + { + await _parser.InsertScriptedInstancesAsync(Capture( + "at 1234 1 79 108 2 0 0 0", + "wp 134 36 0 4 1 99", + "at 1234 132 79 108 2 0 0 0", + "wp 104 55 79 12 81 99")); + + Assert.AreEqual(2, _saved.Count); + Assert.IsFalse(_saved.Single(s => s.MapId == 1).IsHeroic); + Assert.IsTrue(_saved.Single(s => s.MapId == 132).IsHeroic); + } + + [TestMethod] + public async Task OneTimeSpaceReachedFromTwoMapsGivesTwoEntrancesAsync() + { + await _parser.InsertScriptedInstancesAsync(Capture( + "at 1234 132 79 108 2 0 0 0", + "wp 104 55 79 12 81 99", + "at 1234 133 79 108 2 0 0 0", + "wp 36 55 79 12 81 99")); + + Assert.AreEqual(2, _saved.Count); + } + + [TestMethod] + public async Task ARaidPortalBecomesARaidEntranceAsync() + { + await _parser.InsertScriptedInstancesAsync(Capture( + "at 1234 2500 79 108 2 0 0 0", + "gp 24 3 4996 8 0 0")); + + Assert.AreEqual(1, _saved.Count); + Assert.AreEqual(ScriptedInstanceType.Raid, _saved[0].Type); + Assert.AreEqual(2500, _saved[0].MapId); + } + + [TestMethod] + public async Task AnOrdinaryPortalIsNotAnEntranceAsync() + { + await _parser.InsertScriptedInstancesAsync(Capture( + "at 1234 2 79 108 2 0 0 0", + "gp 24 3 1 -1 0 0", + "gp 25 3 1 3 0 0")); + + Assert.AreEqual(0, _saved.Count); + } + + [TestMethod] + public async Task TheSameEntranceAnnouncedOnEveryVisitIsStoredOnceAsync() + { + await _parser.InsertScriptedInstancesAsync(Capture( + "at 1234 1 79 108 2 0 0 0", + "wp 134 36 0 4 1 99", + "at 1234 1 79 108 2 0 0 0", + "wp 134 36 0 4 1 99")); + + Assert.AreEqual(1, _saved.Count); + } + + [TestMethod] + public async Task AnEntranceAlreadyStoredGetsItsMetadataRefreshedAsync() + { + // The columns this parser fills arrive from the migration as 0, 0 and false. Leaving a + // stored row alone therefore keeps every level range at zero for ever, on any database + // that already holds entrances - and nothing reports it. + _existing.Add(new ScriptedInstanceDto + { + ScriptedInstanceId = 7, + MapId = 1, + PositionX = 134, + PositionY = 36, + Script = "..." + }); + + await _parser.InsertScriptedInstancesAsync(Capture( + "at 1234 1 79 108 2 0 0 0", + "wp 134 36 0 4 1 99")); + + var refreshed = _saved.Single(); + Assert.AreEqual(1, refreshed.LevelMinimum); + Assert.AreEqual(99, refreshed.LevelMaximum); + + // The id makes it an update rather than a second row, and the script is not ours to + // overwrite - it is written by whoever authors the instance. + Assert.AreEqual(7, refreshed.ScriptedInstanceId); + Assert.AreEqual("...", refreshed.Script); + } + + [TestMethod] + public async Task OneEntranceSeenTwiceInTheCaptureIsSavedOnceAsync() + { + // The capture walks a map more than once, so the same wp comes round again. + await _parser.InsertScriptedInstancesAsync(Capture( + "at 1234 1 79 108 2 0 0 0", + "wp 134 36 0 4 1 99", + "wp 134 36 0 4 1 99")); + + Assert.AreEqual(1, _saved.Count); + } + + [TestMethod] + public async Task AnEntranceOnAMapTheServerDoesNotHaveIsDroppedAsync() + { + await _parser.InsertScriptedInstancesAsync(Capture( + "at 1234 9999 79 108 2 0 0 0", + "wp 134 36 0 4 1 99")); + + Assert.AreEqual(0, _saved.Count); + } + + [TestMethod] + public async Task ATruncatedLineDoesNotBringTheImportDownAsync() + { + await _parser.InsertScriptedInstancesAsync(Capture( + "at 1234 1 79 108 2 0 0 0", + "wp 134 36", + "gp 24", + "wp 134 36 0 4 1 99")); + + Assert.AreEqual(1, _saved.Count); + } + } +}