diff --git a/Content.Client/UserInterface/HumanoidProfileEditor.cs b/Content.Client/UserInterface/HumanoidProfileEditor.cs index 4c38b7cbee..7558832b0d 100644 --- a/Content.Client/UserInterface/HumanoidProfileEditor.cs +++ b/Content.Client/UserInterface/HumanoidProfileEditor.cs @@ -1,4 +1,4 @@ -using Content.Client.GameObjects.Components; +using Content.Client.GameObjects.Components; using Content.Client.GameObjects.Components.Mobs; using Content.Client.Interfaces; using Content.Shared.GameTicking; @@ -43,6 +43,7 @@ namespace Content.Client.UserInterface private readonly Button _sexMaleButton; private readonly OptionButton _genderButton; private readonly OptionButton _clothingButton; + private readonly OptionButton _backpackButton; private readonly HairStylePicker _hairPicker; private readonly FacialHairStylePicker _facialHairPicker; @@ -333,6 +334,33 @@ namespace Content.Client.UserInterface } #endregion Clothing + + #region Backpack + + { + var panel = HighlightedContainer(); + var hBox = new HBoxContainer(); + var backpackLabel = new Label { Text = Loc.GetString("Backpack:") }; + + _backpackButton = new OptionButton(); + + _backpackButton.AddItem(Loc.GetString("Backpack"), (int) BackpackPreference.Backpack); + _backpackButton.AddItem(Loc.GetString("Satchel"), (int) BackpackPreference.Satchel); + _backpackButton.AddItem(Loc.GetString("Duffelbag"), (int) BackpackPreference.Duffelbag); + + _backpackButton.OnItemSelected += args => + { + _backpackButton.SelectId(args.Id); + SetBackpack((BackpackPreference) args.Id); + }; + + hBox.AddChild(backpackLabel); + hBox.AddChild(_backpackButton); + panel.AddChild(hBox); + appearanceVBox.AddChild(panel); + } + + #endregion Clothing } #endregion @@ -669,6 +697,12 @@ namespace Content.Client.UserInterface IsDirty = true; } + private void SetBackpack(BackpackPreference newBackpack) + { + Profile = Profile?.WithBackpackPreference(newBackpack); + IsDirty = true; + } + public void Save() { IsDirty = false; @@ -723,6 +757,11 @@ namespace Content.Client.UserInterface _clothingButton.SelectId((int) Profile.Clothing); } + private void UpdateBackpackControls() + { + _backpackButton.SelectId((int) Profile.Backpack); + } + private void UpdateHairPickers() { _hairPicker.SetData( @@ -754,6 +793,7 @@ namespace Content.Client.UserInterface UpdateSexControls(); UpdateGenderControls(); UpdateClothingControls(); + UpdateBackpackControls(); UpdateAgeEdit(); UpdateHairPickers(); UpdateSaveButton(); diff --git a/Content.Server.Database/Migrations/Postgres/20210103151756_BackpackPreference.Designer.cs b/Content.Server.Database/Migrations/Postgres/20210103151756_BackpackPreference.Designer.cs new file mode 100644 index 0000000000..1a66e59863 --- /dev/null +++ b/Content.Server.Database/Migrations/Postgres/20210103151756_BackpackPreference.Designer.cs @@ -0,0 +1,575 @@ +// +using System; +using System.Net; +using Content.Server.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +namespace Content.Server.Database.Migrations.Postgres +{ + [DbContext(typeof(PostgresServerDbContext))] + [Migration("20210103151756_BackpackPreference")] + partial class BackpackPreference + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .UseIdentityByDefaultColumns() + .HasAnnotation("Relational:MaxIdentifierLength", 63) + .HasAnnotation("ProductVersion", "5.0.0"); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("AdminRankId") + .HasColumnType("integer") + .HasColumnName("admin_rank_id"); + + b.Property("Title") + .HasColumnType("text") + .HasColumnName("title"); + + b.HasKey("UserId"); + + b.HasIndex("AdminRankId"); + + b.ToTable("admin"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_flag_id") + .UseIdentityByDefaultColumn(); + + b.Property("AdminId") + .HasColumnType("uuid") + .HasColumnName("admin_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("text") + .HasColumnName("flag"); + + b.Property("Negative") + .HasColumnType("boolean") + .HasColumnName("negative"); + + b.HasKey("Id"); + + b.HasIndex("AdminId"); + + b.HasIndex("Flag", "AdminId") + .IsUnique(); + + b.ToTable("admin_flag"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_rank_id") + .UseIdentityByDefaultColumn(); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id"); + + b.ToTable("admin_rank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_rank_flag_id") + .UseIdentityByDefaultColumn(); + + b.Property("AdminRankId") + .HasColumnType("integer") + .HasColumnName("admin_rank_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("text") + .HasColumnName("flag"); + + b.HasKey("Id"); + + b.HasIndex("AdminRankId"); + + b.HasIndex("Flag", "AdminRankId") + .IsUnique(); + + b.ToTable("admin_rank_flag"); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("antag_id") + .UseIdentityByDefaultColumn(); + + b.Property("AntagName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("antag_name"); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.HasKey("Id"); + + b.HasIndex("ProfileId", "AntagName") + .IsUnique(); + + b.ToTable("antag"); + }); + + modelBuilder.Entity("Content.Server.Database.AssignedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("assigned_user_id_id") + .UseIdentityByDefaultColumn(); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("user_name"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("UserName") + .IsUnique(); + + b.ToTable("assigned_user_id"); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("job_id") + .UseIdentityByDefaultColumn(); + + b.Property("JobName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("job_name"); + + b.Property("Priority") + .HasColumnType("integer") + .HasColumnName("priority"); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.HasKey("Id"); + + b.HasIndex("ProfileId"); + + b.ToTable("job"); + }); + + modelBuilder.Entity("Content.Server.Database.PostgresConnectionLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("connection_log_id") + .UseIdentityByDefaultColumn(); + + b.Property("Address") + .IsRequired() + .HasColumnType("inet") + .HasColumnName("address"); + + b.Property("Time") + .HasColumnType("timestamp with time zone") + .HasColumnName("time"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("user_name"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("connection_log"); + + b.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"); + }); + + modelBuilder.Entity("Content.Server.Database.PostgresPlayer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("player_id") + .UseIdentityByDefaultColumn(); + + b.Property("FirstSeenTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("first_seen_time"); + + b.Property("LastSeenAddress") + .IsRequired() + .HasColumnType("inet") + .HasColumnName("last_seen_address"); + + b.Property("LastSeenTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_seen_time"); + + b.Property("LastSeenUserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("last_seen_user_name"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id"); + + b.HasIndex("LastSeenUserName"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("player"); + + b.HasCheckConstraint("LastSeenAddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= last_seen_address"); + }); + + modelBuilder.Entity("Content.Server.Database.PostgresServerBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_ban_id") + .UseIdentityByDefaultColumn(); + + b.Property?>("Address") + .HasColumnType("inet") + .HasColumnName("address"); + + b.Property("BanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("uuid") + .HasColumnName("banning_admin"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id"); + + b.HasIndex("Address"); + + b.HasIndex("UserId"); + + b.ToTable("server_ban"); + + b.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"); + + b.HasCheckConstraint("HaveEitherAddressOrUserId", "address IS NOT NULL OR user_id IS NOT NULL"); + }); + + modelBuilder.Entity("Content.Server.Database.PostgresServerUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("unban_id") + .UseIdentityByDefaultColumn(); + + b.Property("BanId") + .HasColumnType("integer") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("uuid") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_unban"); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("preference_id") + .UseIdentityByDefaultColumn(); + + b.Property("SelectedCharacterSlot") + .HasColumnType("integer") + .HasColumnName("selected_character_slot"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("preference"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_id") + .UseIdentityByDefaultColumn(); + + b.Property("Age") + .HasColumnType("integer") + .HasColumnName("age"); + + b.Property("Backpack") + .IsRequired() + .HasColumnType("text") + .HasColumnName("backpack"); + + b.Property("CharacterName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("char_name"); + + b.Property("Clothing") + .IsRequired() + .HasColumnType("text") + .HasColumnName("clothing"); + + b.Property("EyeColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("eye_color"); + + b.Property("FacialHairColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("facial_hair_color"); + + b.Property("FacialHairName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("facial_hair_name"); + + b.Property("Gender") + .IsRequired() + .HasColumnType("text") + .HasColumnName("gender"); + + b.Property("HairColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("hair_color"); + + b.Property("HairName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("hair_name"); + + b.Property("PreferenceId") + .HasColumnType("integer") + .HasColumnName("preference_id"); + + b.Property("PreferenceUnavailable") + .HasColumnType("integer") + .HasColumnName("pref_unavailable"); + + b.Property("Sex") + .IsRequired() + .HasColumnType("text") + .HasColumnName("sex"); + + b.Property("SkinColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("skin_color"); + + b.Property("Slot") + .HasColumnType("integer") + .HasColumnName("slot"); + + b.HasKey("Id"); + + b.HasIndex("PreferenceId"); + + b.HasIndex("Slot", "PreferenceId") + .IsUnique(); + + b.ToTable("profile"); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.HasOne("Content.Server.Database.AdminRank", "AdminRank") + .WithMany("Admins") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("AdminRank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.HasOne("Content.Server.Database.Admin", "Admin") + .WithMany("Flags") + .HasForeignKey("AdminId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Admin"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.HasOne("Content.Server.Database.AdminRank", "Rank") + .WithMany("Flags") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Rank"); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Antags") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Jobs") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.PostgresServerUnban", b => + { + b.HasOne("Content.Server.Database.PostgresServerBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.PostgresServerUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.HasOne("Content.Server.Database.Preference", "Preference") + .WithMany("Profiles") + .HasForeignKey("PreferenceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Preference"); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Navigation("Admins"); + + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.PostgresServerBan", b => + { + b.Navigation("Unban"); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Navigation("Profiles"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Navigation("Antags"); + + b.Navigation("Jobs"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Content.Server.Database/Migrations/Postgres/20210103151756_BackpackPreference.cs b/Content.Server.Database/Migrations/Postgres/20210103151756_BackpackPreference.cs new file mode 100644 index 0000000000..0c5a7356bb --- /dev/null +++ b/Content.Server.Database/Migrations/Postgres/20210103151756_BackpackPreference.cs @@ -0,0 +1,24 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Content.Server.Database.Migrations.Postgres +{ + public partial class BackpackPreference : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "backpack", + table: "profile", + type: "text", + nullable: false, + defaultValue: ""); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "backpack", + table: "profile"); + } + } +} diff --git a/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs b/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs index 589940e4a6..b7a48063b5 100644 --- a/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs +++ b/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs @@ -386,6 +386,11 @@ namespace Content.Server.Database.Migrations.Postgres .HasColumnType("integer") .HasColumnName("age"); + b.Property("Backpack") + .IsRequired() + .HasColumnType("text") + .HasColumnName("backpack"); + b.Property("CharacterName") .IsRequired() .HasColumnType("text") diff --git a/Content.Server.Database/Migrations/Sqlite/20210103151752_BackpackPreference.Designer.cs b/Content.Server.Database/Migrations/Sqlite/20210103151752_BackpackPreference.Designer.cs new file mode 100644 index 0000000000..661cfbc318 --- /dev/null +++ b/Content.Server.Database/Migrations/Sqlite/20210103151752_BackpackPreference.Designer.cs @@ -0,0 +1,542 @@ +// +using System; +using Content.Server.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace Content.Server.Database.Migrations.Sqlite +{ + [DbContext(typeof(SqliteServerDbContext))] + [Migration("20210103151752_BackpackPreference")] + partial class BackpackPreference + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "5.0.0"); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("AdminRankId") + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_id"); + + b.Property("Title") + .HasColumnType("TEXT") + .HasColumnName("title"); + + b.HasKey("UserId"); + + b.HasIndex("AdminRankId"); + + b.ToTable("admin"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_flag_id"); + + b.Property("AdminId") + .HasColumnType("TEXT") + .HasColumnName("admin_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("flag"); + + b.Property("Negative") + .HasColumnType("INTEGER") + .HasColumnName("negative"); + + b.HasKey("Id"); + + b.HasIndex("AdminId"); + + b.HasIndex("Flag", "AdminId") + .IsUnique(); + + b.ToTable("admin_flag"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_id"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("name"); + + b.HasKey("Id"); + + b.ToTable("admin_rank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_flag_id"); + + b.Property("AdminRankId") + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("flag"); + + b.HasKey("Id"); + + b.HasIndex("AdminRankId"); + + b.HasIndex("Flag", "AdminRankId") + .IsUnique(); + + b.ToTable("admin_rank_flag"); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("antag_id"); + + b.Property("AntagName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("antag_name"); + + b.Property("ProfileId") + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.HasKey("Id"); + + b.HasIndex("ProfileId", "AntagName") + .IsUnique(); + + b.ToTable("antag"); + }); + + modelBuilder.Entity("Content.Server.Database.AssignedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("assigned_user_id_id"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("user_name"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("UserName") + .IsUnique(); + + b.ToTable("assigned_user_id"); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("job_id"); + + b.Property("JobName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("job_name"); + + b.Property("Priority") + .HasColumnType("INTEGER") + .HasColumnName("priority"); + + b.Property("ProfileId") + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.HasKey("Id"); + + b.HasIndex("ProfileId"); + + b.ToTable("job"); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("preference_id"); + + b.Property("SelectedCharacterSlot") + .HasColumnType("INTEGER") + .HasColumnName("selected_character_slot"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("preference"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.Property("Age") + .HasColumnType("INTEGER") + .HasColumnName("age"); + + b.Property("Backpack") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("backpack"); + + b.Property("CharacterName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("char_name"); + + b.Property("Clothing") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("clothing"); + + b.Property("EyeColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("eye_color"); + + b.Property("FacialHairColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("facial_hair_color"); + + b.Property("FacialHairName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("facial_hair_name"); + + b.Property("Gender") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("gender"); + + b.Property("HairColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("hair_color"); + + b.Property("HairName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("hair_name"); + + b.Property("PreferenceId") + .HasColumnType("INTEGER") + .HasColumnName("preference_id"); + + b.Property("PreferenceUnavailable") + .HasColumnType("INTEGER") + .HasColumnName("pref_unavailable"); + + b.Property("Sex") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("sex"); + + b.Property("SkinColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("skin_color"); + + b.Property("Slot") + .HasColumnType("INTEGER") + .HasColumnName("slot"); + + b.HasKey("Id"); + + b.HasIndex("PreferenceId"); + + b.HasIndex("Slot", "PreferenceId") + .IsUnique(); + + b.ToTable("profile"); + }); + + modelBuilder.Entity("Content.Server.Database.SqliteConnectionLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("connection_log_id"); + + b.Property("Address") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("address"); + + b.Property("Time") + .HasColumnType("TEXT") + .HasColumnName("time"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("user_name"); + + b.HasKey("Id"); + + b.ToTable("connection_log"); + }); + + modelBuilder.Entity("Content.Server.Database.SqlitePlayer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("player_id"); + + b.Property("FirstSeenTime") + .HasColumnType("TEXT") + .HasColumnName("first_seen_time"); + + b.Property("LastSeenAddress") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_seen_address"); + + b.Property("LastSeenTime") + .HasColumnType("TEXT") + .HasColumnName("last_seen_time"); + + b.Property("LastSeenUserName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_seen_user_name"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("Id"); + + b.HasIndex("LastSeenUserName"); + + b.ToTable("player"); + }); + + modelBuilder.Entity("Content.Server.Database.SqliteServerBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("ban_id"); + + b.Property("Address") + .HasColumnType("TEXT") + .HasColumnName("address"); + + b.Property("BanTime") + .HasColumnType("TEXT") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("banning_admin"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("reason"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("Id"); + + b.ToTable("ban"); + }); + + modelBuilder.Entity("Content.Server.Database.SqliteServerUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("unban_id"); + + b.Property("BanId") + .HasColumnType("INTEGER") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("TEXT") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("unban"); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.HasOne("Content.Server.Database.AdminRank", "AdminRank") + .WithMany("Admins") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("AdminRank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.HasOne("Content.Server.Database.Admin", "Admin") + .WithMany("Flags") + .HasForeignKey("AdminId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Admin"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.HasOne("Content.Server.Database.AdminRank", "Rank") + .WithMany("Flags") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Rank"); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Antags") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Jobs") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.HasOne("Content.Server.Database.Preference", "Preference") + .WithMany("Profiles") + .HasForeignKey("PreferenceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Preference"); + }); + + modelBuilder.Entity("Content.Server.Database.SqliteServerUnban", b => + { + b.HasOne("Content.Server.Database.SqliteServerBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.SqliteServerUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Navigation("Admins"); + + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Navigation("Profiles"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Navigation("Antags"); + + b.Navigation("Jobs"); + }); + + modelBuilder.Entity("Content.Server.Database.SqliteServerBan", b => + { + b.Navigation("Unban"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Content.Server.Database/Migrations/Sqlite/20210103151752_BackpackPreference.cs b/Content.Server.Database/Migrations/Sqlite/20210103151752_BackpackPreference.cs new file mode 100644 index 0000000000..ff907ca1f2 --- /dev/null +++ b/Content.Server.Database/Migrations/Sqlite/20210103151752_BackpackPreference.cs @@ -0,0 +1,24 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Content.Server.Database.Migrations.Sqlite +{ + public partial class BackpackPreference : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "backpack", + table: "profile", + type: "TEXT", + nullable: false, + defaultValue: ""); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "backpack", + table: "profile"); + } + } +} diff --git a/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs b/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs index f6c1eb5e3a..8e93f4acbf 100644 --- a/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs +++ b/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs @@ -223,6 +223,11 @@ namespace Content.Server.Database.Migrations.Sqlite .HasColumnType("INTEGER") .HasColumnName("age"); + b.Property("Backpack") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("backpack"); + b.Property("CharacterName") .IsRequired() .HasColumnType("TEXT") diff --git a/Content.Server.Database/Model.cs b/Content.Server.Database/Model.cs index e5d365b602..ed5c51e8c6 100644 --- a/Content.Server.Database/Model.cs +++ b/Content.Server.Database/Model.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; @@ -99,6 +99,7 @@ namespace Content.Server.Database [Column("eye_color")] public string EyeColor { get; set; } = null!; [Column("skin_color")] public string SkinColor { get; set; } = null!; [Column("clothing")] public string Clothing { get; set; } = null!; + [Column("backpack")] public string Backpack { get; set; } = null!; public List Jobs { get; } = new(); public List Antags { get; } = new(); diff --git a/Content.Server/Database/ServerDbBase.cs b/Content.Server/Database/ServerDbBase.cs index 929532fc21..0d95804350 100644 --- a/Content.Server/Database/ServerDbBase.cs +++ b/Content.Server/Database/ServerDbBase.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using System; using System.Collections.Generic; using System.Linq; @@ -140,6 +140,10 @@ namespace Content.Server.Database if (Enum.TryParse(profile.Clothing, true, out var clothingVal)) clothing = clothingVal; + var backpack = BackpackPreference.Backpack; + if (Enum.TryParse(profile.Backpack, true, out var backpackVal)) + backpack = backpackVal; + var gender = sex == Sex.Male ? Gender.Male : Gender.Female; if (Enum.TryParse(profile.Gender, true, out var genderVal)) gender = genderVal; @@ -159,6 +163,7 @@ namespace Content.Server.Database Color.FromHex(profile.SkinColor) ), clothing, + backpack, jobs, (PreferenceUnavailableMode) profile.PreferenceUnavailable, antags.ToList() @@ -182,6 +187,7 @@ namespace Content.Server.Database EyeColor = appearance.EyeColor.ToHex(), SkinColor = appearance.SkinColor.ToHex(), Clothing = humanoid.Clothing.ToString(), + Backpack = humanoid.Backpack.ToString(), Slot = slot, PreferenceUnavailable = (DbPreferenceUnavailableMode) humanoid.PreferenceUnavailable }; diff --git a/Content.Shared/Preferences/BackpackPreference.cs b/Content.Shared/Preferences/BackpackPreference.cs new file mode 100644 index 0000000000..da2c4b8fe8 --- /dev/null +++ b/Content.Shared/Preferences/BackpackPreference.cs @@ -0,0 +1,12 @@ +namespace Content.Shared.Preferences +{ + /// + /// The backpack preference for a profile. Stored in database! + /// + public enum BackpackPreference + { + Backpack, + Satchel, + Duffelbag + } +} diff --git a/Content.Shared/Preferences/HumanoidCharacterProfile.cs b/Content.Shared/Preferences/HumanoidCharacterProfile.cs index 53777695ea..6609591887 100644 --- a/Content.Shared/Preferences/HumanoidCharacterProfile.cs +++ b/Content.Shared/Preferences/HumanoidCharacterProfile.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using System; using System.Collections.Generic; using System.Linq; @@ -34,6 +34,7 @@ namespace Content.Shared.Preferences Gender gender, HumanoidCharacterAppearance appearance, ClothingPreference clothing, + BackpackPreference backpack, Dictionary jobPriorities, PreferenceUnavailableMode preferenceUnavailable, List antagPreferences) @@ -44,6 +45,7 @@ namespace Content.Shared.Preferences Gender = gender; Appearance = appearance; Clothing = clothing; + Backpack = backpack; _jobPriorities = jobPriorities; PreferenceUnavailable = preferenceUnavailable; _antagPreferences = antagPreferences; @@ -54,7 +56,7 @@ namespace Content.Shared.Preferences HumanoidCharacterProfile other, Dictionary jobPriorities, List antagPreferences) - : this(other.Name, other.Age, other.Sex, other.Gender, other.Appearance, other.Clothing, + : this(other.Name, other.Age, other.Sex, other.Gender, other.Appearance, other.Clothing, other.Backpack, jobPriorities, other.PreferenceUnavailable, antagPreferences) { } @@ -72,10 +74,11 @@ namespace Content.Shared.Preferences Gender gender, HumanoidCharacterAppearance appearance, ClothingPreference clothing, + BackpackPreference backpack, IReadOnlyDictionary jobPriorities, PreferenceUnavailableMode preferenceUnavailable, IReadOnlyList antagPreferences) - : this(name, age, sex, gender, appearance, clothing, new Dictionary(jobPriorities), + : this(name, age, sex, gender, appearance, clothing, backpack, new Dictionary(jobPriorities), preferenceUnavailable, new List(antagPreferences)) { } @@ -98,7 +101,7 @@ namespace Content.Shared.Preferences var name = $"{firstName} {lastName}"; var age = random.Next(MinimumAge, MaximumAge); - return new HumanoidCharacterProfile(name, age, sex, gender, HumanoidCharacterAppearance.Random(sex), ClothingPreference.Jumpsuit, + return new HumanoidCharacterProfile(name, age, sex, gender, HumanoidCharacterAppearance.Random(sex), ClothingPreference.Jumpsuit, BackpackPreference.Backpack, new Dictionary { {SharedGameTicker.OverflowJob, JobPriority.High} @@ -112,6 +115,7 @@ namespace Content.Shared.Preferences public ICharacterAppearance CharacterAppearance => Appearance; public HumanoidCharacterAppearance Appearance { get; private set; } public ClothingPreference Clothing { get; private set; } + public BackpackPreference Backpack { get; private set; } public IReadOnlyDictionary JobPriorities => _jobPriorities; public IReadOnlyList AntagPreferences => _antagPreferences; public PreferenceUnavailableMode PreferenceUnavailable { get; private set; } @@ -145,7 +149,10 @@ namespace Content.Shared.Preferences { return new(this) { Clothing = clothing }; } - + public HumanoidCharacterProfile WithBackpackPreference(BackpackPreference backpack) + { + return new(this) { Backpack = backpack }; + } public HumanoidCharacterProfile WithJobPriorities(IEnumerable> jobPriorities) { return new(this, new Dictionary(jobPriorities), _antagPreferences); @@ -254,6 +261,14 @@ namespace Content.Shared.Preferences _ => ClothingPreference.Jumpsuit // Invalid enum values. }; + var backpack = profile.Backpack switch + { + BackpackPreference.Backpack => BackpackPreference.Backpack, + BackpackPreference.Satchel => BackpackPreference.Satchel, + BackpackPreference.Duffelbag => BackpackPreference.Duffelbag, + _ => BackpackPreference.Backpack // Invalid enum values. + }; + var priorities = new Dictionary(profile.JobPriorities .Where(p => prototypeManager.HasIndex(p.Key) && p.Value switch { @@ -268,7 +283,7 @@ namespace Content.Shared.Preferences .Where(prototypeManager.HasIndex) .ToList(); - return new HumanoidCharacterProfile(name, age, sex, gender, appearance, clothing, priorities, prefsUnavailableMode, antags); + return new HumanoidCharacterProfile(name, age, sex, gender, appearance, clothing, backpack, priorities, prefsUnavailableMode, antags); } public string Summary => @@ -283,6 +298,7 @@ namespace Content.Shared.Preferences if (Gender != other.Gender) return false; if (PreferenceUnavailable != other.PreferenceUnavailable) return false; if (Clothing != other.Clothing) return false; + if (Backpack != other.Backpack) return false; if (!_jobPriorities.SequenceEqual(other._jobPriorities)) return false; if (!_antagPreferences.SequenceEqual(other._antagPreferences)) return false; return Appearance.MemberwiseEquals(other.Appearance); @@ -302,7 +318,8 @@ namespace Content.Shared.Preferences Sex, Gender, Appearance, - Clothing + Clothing, + Backpack ), PreferenceUnavailable, _jobPriorities, diff --git a/Content.Shared/Roles/StartingGearPrototype.cs b/Content.Shared/Roles/StartingGearPrototype.cs index ac27be7a56..567a66f181 100644 --- a/Content.Shared/Roles/StartingGearPrototype.cs +++ b/Content.Shared/Roles/StartingGearPrototype.cs @@ -21,6 +21,8 @@ namespace Content.Shared.Roles /// if empty, there is no skirt override - instead the uniform provided in equipment is added. /// private string _innerClothingSkirt = default!; + private string _satchel = default!; + private string _duffelbag = default!; public IReadOnlyDictionary Inhand => _inHand; /// @@ -51,6 +53,8 @@ namespace Content.Shared.Roles }, type => type.Value); serializer.DataField(ref _innerClothingSkirt, "innerclothingskirt", string.Empty); + serializer.DataField(ref _satchel, "satchel", string.Empty); + serializer.DataField(ref _duffelbag, "duffelbag", string.Empty); } public string GetGear(Slots slot, HumanoidCharacterProfile? profile) @@ -59,6 +63,10 @@ namespace Content.Shared.Roles { if ((slot == Slots.INNERCLOTHING) && (profile.Clothing == ClothingPreference.Jumpskirt) && (_innerClothingSkirt != "")) return _innerClothingSkirt; + if ((slot == Slots.BACKPACK) && (profile.Backpack == BackpackPreference.Satchel) && (_satchel != "")) + return _satchel; + if ((slot == Slots.BACKPACK) && (profile.Backpack == BackpackPreference.Duffelbag) && (_duffelbag != "")) + return _duffelbag; } if (_equipment.ContainsKey(slot)) diff --git a/Content.Tests/Server/Preferences/ServerDbSqliteTests.cs b/Content.Tests/Server/Preferences/ServerDbSqliteTests.cs index 2481c5cf88..b8a55e8792 100644 --- a/Content.Tests/Server/Preferences/ServerDbSqliteTests.cs +++ b/Content.Tests/Server/Preferences/ServerDbSqliteTests.cs @@ -36,6 +36,7 @@ namespace Content.Tests.Server.Preferences Color.Beige ), ClothingPreference.Jumpskirt, + BackpackPreference.Backpack, new Dictionary { {SharedGameTicker.OverflowJob, JobPriority.High} diff --git a/Resources/Prototypes/Catalog/Fills/backpack.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/Starter Gear/backpack.yml similarity index 100% rename from Resources/Prototypes/Catalog/Fills/backpack.yml rename to Resources/Prototypes/Catalog/Fills/Backpacks/Starter Gear/backpack.yml diff --git a/Resources/Prototypes/Catalog/Fills/Backpacks/Starter Gear/duffelbag.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/Starter Gear/duffelbag.yml new file mode 100644 index 0000000000..a359dfbd49 --- /dev/null +++ b/Resources/Prototypes/Catalog/Fills/Backpacks/Starter Gear/duffelbag.yml @@ -0,0 +1,75 @@ +- type: entity + abstract: true + parent: ClothingBackpackDuffel + id: ClothingBackpackDuffelFilled + components: + - type: StorageFill + contents: + - name: BoxSurvival + +- type: entity + abstract: true + parent: ClothingBackpackDuffelClown + id: ClothingBackpackDuffelClownFilled + components: + - type: StorageFill + contents: + - name: BoxHug + +- type: entity + abstract: true + parent: ClothingBackpackDuffelSecurity + id: ClothingBackpackDuffelSecurityFilled + components: + - type: StorageFill + contents: + - name: BoxSurvival + - name: Stunbaton + - name: Flash + +- type: entity + abstract: true + parent: ClothingBackpackDuffelMedical + id: ClothingBackpackDuffelMedicalFilled + components: + - type: StorageFill + contents: + - name: BoxSurvival + +- type: entity + abstract: true + parent: ClothingBackpackDuffelCaptain + id: ClothingBackpackDuffelCaptainFilled + components: + - type: StorageFill + contents: + - name: BoxSurvival + #- name: StationCharter + #- name: TelescopicBaton + +- type: entity + abstract: true + parent: ClothingBackpackDuffelEngineering + id: ClothingBackpackDuffelEngineeringFilled + components: + - type: StorageFill + contents: + - name: BoxSurvival + +#- type: entity +# abstract: true +# parent: ClothingBackpackDuffelScience +# id: ClothingBackpackDuffelScienceFilled +# components: +# - type: StorageFill +# contents: +# - name: BoxSurvival + +#- type: entity +# abstract: true +# parent: ClothingBackpackDuffelChemistry +# id: ClothingBackpackDuffelChemistryFilled +# components: +# - type: StorageFill +# contents: +# - name: BoxSurvival diff --git a/Resources/Prototypes/Catalog/Fills/Backpacks/Starter Gear/satchel.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/Starter Gear/satchel.yml new file mode 100644 index 0000000000..a53b54fa07 --- /dev/null +++ b/Resources/Prototypes/Catalog/Fills/Backpacks/Starter Gear/satchel.yml @@ -0,0 +1,75 @@ +- type: entity + abstract: true + parent: ClothingBackpackSatchel + id: ClothingBackpackSatchelFilled + components: + - type: StorageFill + contents: + - name: BoxSurvival + +#- type: entity +# abstract: true +# parent: ClothingBackpackSatchelClown +# id: ClothingBackpackSatchelClownFilled +# components: +# - type: StorageFill +# contents: +# - name: BoxHug + +- type: entity + abstract: true + parent: ClothingBackpackSatchelSecurity + id: ClothingBackpackSatchelSecurityFilled + components: + - type: StorageFill + contents: + - name: BoxSurvival + - name: Stunbaton + - name: Flash + +- type: entity + abstract: true + parent: ClothingBackpackSatchelMedical + id: ClothingBackpackSatchelMedicalFilled + components: + - type: StorageFill + contents: + - name: BoxSurvival + +- type: entity + abstract: true + parent: ClothingBackpackSatchelCaptain + id: ClothingBackpackSatchelCaptainFilled + components: + - type: StorageFill + contents: + - name: BoxSurvival + #- name: StationCharter + #- name: TelescopicBaton + +- type: entity + abstract: true + parent: ClothingBackpackSatchelEngineering + id: ClothingBackpackSatchelEngineeringFilled + components: + - type: StorageFill + contents: + - name: BoxSurvival + +- type: entity + abstract: true + parent: ClothingBackpackSatchelScience + id: ClothingBackpackSatchelScienceFilled + components: + - type: StorageFill + contents: + - name: BoxSurvival + +- type: entity + abstract: true + parent: ClothingBackpackSatchelChemistry + id: ClothingBackpackSatchelChemistryFilled + components: + - type: StorageFill + contents: + - name: BoxSurvival diff --git a/Resources/Prototypes/Catalog/Fills/duffel.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/duffelbag.yml similarity index 100% rename from Resources/Prototypes/Catalog/Fills/duffel.yml rename to Resources/Prototypes/Catalog/Fills/Backpacks/duffelbag.yml diff --git a/Resources/Prototypes/Roles/Jobs/Cargo/cargo_technician.yml b/Resources/Prototypes/Roles/Jobs/Cargo/cargo_technician.yml index cfaaf58949..767eee8a88 100644 --- a/Resources/Prototypes/Roles/Jobs/Cargo/cargo_technician.yml +++ b/Resources/Prototypes/Roles/Jobs/Cargo/cargo_technician.yml @@ -21,4 +21,5 @@ idcard: CargoPDA ears: ClothingHeadsetCargo innerclothingskirt: ClothingUniformJumpskirtCargo - + satchel: ClothingBackpackSatchelFilled + duffelbag: ClothingBackpackDuffelFilled diff --git a/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml b/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml index e5dced21f9..3d9eabe13b 100644 --- a/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml +++ b/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml @@ -22,4 +22,5 @@ idcard: QuartermasterPDA ears: ClothingHeadsetCargo innerclothingskirt: ClothingUniformJumpskirtQM - + satchel: ClothingBackpackSatchelFilled + duffelbag: ClothingBackpackDuffelFilled diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/assistant.yml b/Resources/Prototypes/Roles/Jobs/Civilian/assistant.yml index 6249154a98..be5e8f29ab 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/assistant.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/assistant.yml @@ -18,4 +18,5 @@ idcard: AssistantPDA ears: ClothingHeadsetService innerclothingskirt: ClothingUniformJumpskirtColorGrey - + satchel: ClothingBackpackSatchelFilled + duffelbag: ClothingBackpackDuffelFilled diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/bartender.yml b/Resources/Prototypes/Roles/Jobs/Civilian/bartender.yml index 761e2f7ccd..c62541346d 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/bartender.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/bartender.yml @@ -22,4 +22,5 @@ idcard: BartenderPDA ears: ClothingHeadsetService innerclothingskirt: ClothingUniformJumpskirtBartender - + satchel: ClothingBackpackSatchelFilled + duffelbag: ClothingBackpackDuffelFilled diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/botanist.yml b/Resources/Prototypes/Roles/Jobs/Civilian/botanist.yml index 59bdfd5db7..462bb1d2f2 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/botanist.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/botanist.yml @@ -22,4 +22,5 @@ ears: ClothingHeadsetService outerclothing: ClothingOuterApronBotanist innerclothingskirt: ClothingUniformJumpskirtHydroponics - + satchel: ClothingBackpackSatchelFilled + duffelbag: ClothingBackpackDuffelFilled diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/chef.yml b/Resources/Prototypes/Roles/Jobs/Civilian/chef.yml index c4e0fb978b..a49a15e6ab 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/chef.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/chef.yml @@ -22,4 +22,5 @@ ears: ClothingHeadsetService outerclothing: ClothingOuterApronChef innerclothingskirt: ClothingUniformJumpskirtChef - + satchel: ClothingBackpackSatchelFilled + duffelbag: ClothingBackpackDuffelFilled diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml b/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml index 15bdd058e8..46ef1db39b 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml @@ -21,3 +21,4 @@ pocket1: BikeHorn idcard: ClownPDA ears: ClothingHeadsetService + duffelbag: ClothingBackpackDuffelClownFilled diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/janitor.yml b/Resources/Prototypes/Roles/Jobs/Civilian/janitor.yml index 5cd9cdabd6..b294e5e463 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/janitor.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/janitor.yml @@ -21,4 +21,5 @@ ears: ClothingHeadsetService belt: ClothingBeltJanitorFilled innerclothingskirt: ClothingUniformJumpskirtJanitor - + satchel: ClothingBackpackSatchelFilled + duffelbag: ClothingBackpackDuffelFilled diff --git a/Resources/Prototypes/Roles/Jobs/Command/captain.yml b/Resources/Prototypes/Roles/Jobs/Command/captain.yml index 2000efb720..165ef640b9 100644 --- a/Resources/Prototypes/Roles/Jobs/Command/captain.yml +++ b/Resources/Prototypes/Roles/Jobs/Command/captain.yml @@ -48,3 +48,5 @@ outerclothing: ClothingOuterHardsuitCap idcard: CaptainPDA ears: ClothingHeadsetAltCommand + satchel: ClothingBackpackSatchelCaptainFilled + duffelbag: ClothingBackpackDuffelCaptainFilled diff --git a/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml b/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml index 5558880f74..70dc494506 100644 --- a/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml +++ b/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml @@ -29,4 +29,5 @@ idcard: HoPPDA ears: ClothingHeadsetAltCommand innerclothingskirt: ClothingUniformJumpskirtHoP - + satchel: ClothingBackpackSatchelFilled + duffelbag: ClothingBackpackDuffelFilled diff --git a/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml b/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml index d029293184..6bcff4639b 100644 --- a/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml +++ b/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml @@ -26,4 +26,5 @@ ears: ClothingHeadsetEngineering belt: ClothingBeltChiefEngineerFilled innerclothingskirt: ClothingUniformJumpskirtChiefEngineer - + satchel: ClothingBackpackSatchelEngineeringFilled + duffelbag: ClothingBackpackDuffelEngineeringFilled diff --git a/Resources/Prototypes/Roles/Jobs/Engineering/station_engineer.yml b/Resources/Prototypes/Roles/Jobs/Engineering/station_engineer.yml index a7fa9b5d13..0b702ca6b6 100644 --- a/Resources/Prototypes/Roles/Jobs/Engineering/station_engineer.yml +++ b/Resources/Prototypes/Roles/Jobs/Engineering/station_engineer.yml @@ -24,4 +24,5 @@ belt: ClothingBeltUtilityFilled ears: ClothingHeadsetEngineering innerclothingskirt: ClothingUniformJumpskirtEngineering - + satchel: ClothingBackpackSatchelEngineeringFilled + duffelbag: ClothingBackpackDuffelEngineeringFilled diff --git a/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml b/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml index c29a91a31c..4b06c0559a 100644 --- a/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml +++ b/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml @@ -27,4 +27,5 @@ ears: ClothingHeadsetAltMedical belt: ClothingBeltMedical innerclothingskirt: ClothingUniformJumpskirtCMO - + satchel: ClothingBackpackSatchelMedicalFilled + duffelbag: ClothingBackpackDuffelMedicalFilled diff --git a/Resources/Prototypes/Roles/Jobs/Medical/medical_doctor.yml b/Resources/Prototypes/Roles/Jobs/Medical/medical_doctor.yml index 3e34d75574..81c9dd8ba0 100644 --- a/Resources/Prototypes/Roles/Jobs/Medical/medical_doctor.yml +++ b/Resources/Prototypes/Roles/Jobs/Medical/medical_doctor.yml @@ -22,4 +22,5 @@ ears: ClothingHeadsetMedical belt: ClothingBeltMedical innerclothingskirt: ClothingUniformJumpskirtMedicalDoctor - + satchel: ClothingBackpackSatchelMedicalFilled + duffelbag: ClothingBackpackDuffelMedicalFilled diff --git a/Resources/Prototypes/Roles/Jobs/Science/research_director.yml b/Resources/Prototypes/Roles/Jobs/Science/research_director.yml index 32202b4a79..7a89465e6d 100644 --- a/Resources/Prototypes/Roles/Jobs/Science/research_director.yml +++ b/Resources/Prototypes/Roles/Jobs/Science/research_director.yml @@ -23,4 +23,4 @@ idcard: RnDPDA ears: ClothingHeadsetScience innerclothingskirt: ClothingUniformJumpskirtResearchDirector - + satchel: ClothingBackpackSatchelScienceFilled diff --git a/Resources/Prototypes/Roles/Jobs/Science/scientist.yml b/Resources/Prototypes/Roles/Jobs/Science/scientist.yml index 9d2c43eee9..e37628b019 100644 --- a/Resources/Prototypes/Roles/Jobs/Science/scientist.yml +++ b/Resources/Prototypes/Roles/Jobs/Science/scientist.yml @@ -21,4 +21,4 @@ idcard: SciencePDA ears: ClothingHeadsetScience innerclothingskirt: ClothingUniformJumpskirtScientist - + satchel: ClothingBackpackSatchelScienceFilled diff --git a/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml b/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml index 176222aa33..ffb90f4f16 100644 --- a/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml +++ b/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml @@ -30,4 +30,5 @@ ears: ClothingHeadsetAltSecurity belt: ClothingBeltSecurityFilled innerclothingskirt: ClothingUniformJumpskirtHoS - + satchel: ClothingBackpackSatchelSecurityFilled + duffelbag: ClothingBackpackDuffelSecurityFilled diff --git a/Resources/Prototypes/Roles/Jobs/Security/security_officer.yml b/Resources/Prototypes/Roles/Jobs/Security/security_officer.yml index d9356cf6b3..07bc658f6a 100644 --- a/Resources/Prototypes/Roles/Jobs/Security/security_officer.yml +++ b/Resources/Prototypes/Roles/Jobs/Security/security_officer.yml @@ -25,4 +25,5 @@ ears: ClothingHeadsetSecurity belt: ClothingBeltSecurityFilled innerclothingskirt: ClothingUniformJumpskirtSec - + satchel: ClothingBackpackSatchelSecurityFilled + duffelbag: ClothingBackpackDuffelSecurityFilled diff --git a/Resources/Prototypes/Roles/Jobs/Security/warden.yml b/Resources/Prototypes/Roles/Jobs/Security/warden.yml index c9d250f9e0..9051a5f796 100644 --- a/Resources/Prototypes/Roles/Jobs/Security/warden.yml +++ b/Resources/Prototypes/Roles/Jobs/Security/warden.yml @@ -26,4 +26,5 @@ ears: ClothingHeadsetSecurity belt: ClothingBeltSecurityFilled innerclothingskirt: ClothingUniformJumpskirtWarden - + satchel: ClothingBackpackSatchelSecurityFilled + duffelbag: ClothingBackpackDuffelSecurityFilled